1  /-
  2  Copyright (c) 2015 Microsoft Corporation. All rights reserved.
  3  Released under Apache 2.0 license as described in the file LICENSE.
  4  Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
  5  
  6  List permutations.
  7  -/
  8  import data.list.basic logic.relation
src         └─────────────┘ └────────────┘
  9  
 10  namespace list
 11  universe variables uu vv
 12  variables {α : Type uu} {β : Type vv}
 13  
 14  /-- `perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
 15    of each other. This is defined by induction using pairwise swaps. -/
 16  inductive perm : list α → list α → Prop
id                    └──┘     └──┘
src                   └──┘     └──┘
typ                   └──┘     └──┘
 17  | nil   : perm [] []
id                  └┘ └┘
src                 └┘ └┘
typ                 └┘ └┘
 18  | skip  : Π (x : α) {l₁ l₂ : list α}, perm l₁ l₂ → perm (x::l₁) (x::l₂)
id                                └──┘     └──┘ └┘ └┘         └┘└┘   └┘└┘
src                               └──┘                         └┘      └┘
typ                               └──┘     └──┘ └┘ └┘         └┘└┘   └┘└┘
 19  | swap  : Π (x y : α) (l : list α), perm (y::x::l) (x::y::l)
id                              └──┘           └┘└┘   └┘└┘
src                             └──┘            └┘ └┘     └┘ └┘
typ                             └──┘           └┘└┘   └┘└┘
 20  | trans : Π {l₁ l₂ l₃ : list α}, perm l₁ l₂ → perm l₂ l₃ → perm l₁ l₃
id                           └──┘     └──┘ └┘ └┘   └──┘ └┘ └┘        └┘ └┘
src                          └──┘
typ                          └──┘     └──┘ └┘ └┘   └──┘ └┘ └┘        └┘ └┘
 21  open perm
 22  
 23  infix ~ := perm
id              └──┘
src             └──┘
typ             └──┘
doc             └──┘
 24  
 25  @[refl] protected theorem perm.refl : ∀ (l : list α), l ~ l
id                                               └──┘      
src    └──┘                                       └──┘       
typ                                              └──┘      
doc    └──┘                                                  
 26  | []      := perm.nil
id     └┘         └──────┘
src    └┘         └──────┘
typ    └┘         └──────┘
 27  | (x::xs) := skip x (perm.refl xs)
id      └┘└┘     └──┘    └───────┘
src      └┘       └──┘
typ     └┘└┘     └──┘    └───────┘
 28  
 29  @[symm] protected theorem perm.symm {l₁ l₂ : list α} (p : l₁ ~ l₂) : l₂ ~ l₁ :=
id                                                └──┘        └┘  └┘    └┘  └┘
src    └──┘                                       └──┘                      
typ                                               └──┘        └┘  └┘    └┘  └┘
doc    └──┘                                                                 
 30  perm.rec_on p
id   └─────────┘ 
src  └─────────┘
typ  └─────────┘ 
 31    perm.nil
id     └──────┘
src    └──────┘
typ    └──────┘
 32    (λ x l₁ l₂ p₁ r₁, skip x r₁)
id         └┘ └┘ └┘ └┘  └──┘  └┘
src                      └──┘
typ        └┘ └┘ └┘ └┘  └──┘  └┘
 33    (λ x y l, swap y x l)
id            └──┘   
src              └──┘
typ           └──┘   
 34    (λ l₁ l₂ l₃ p₁ p₂ r₁ r₂, trans r₂ r₁)
id        └┘ └┘ └┘ └┘ └┘ └┘ └┘  └───┘ └┘ └┘
src                             └───┘
typ       └┘ └┘ └┘ └┘ └┘ └┘ └┘  └───┘ └┘ └┘
 35  
 36  theorem perm.swap'
 37    (x y : α) {l₁ l₂ : list α} (p : l₁ ~ l₂) : y::x::l₁ ~ x::y::l₂ :=
id                       └──┘        └┘  └┘    └┘└┘└┘  └┘└┘└┘
src                       └──┘                    └┘ └┘     └┘ └┘
typ                      └──┘        └┘  └┘    └┘└┘└┘  └┘└┘└┘
doc                                                       
 38  trans (swap _ _ _) (skip _ $ skip _ p)
id   └───┘  └──┘         └──┘     └──┘   
src  └───┘  └──┘         └──┘     └──┘
typ  └───┘  └──┘         └──┘     └──┘   
 39  
 40  attribute [trans] perm.trans
id                     └────────┘
src             └───┘  └────────┘
typ                    └────────┘
doc             └───┘
 41  
 42  theorem perm.eqv (α) : equivalence (@perm α) :=
id                          └─────────┘   └──┘ 
src                         └─────────┘   └──┘
typ                         └─────────┘   └──┘ 
doc                                       └──┘
 43  mk_equivalence (@perm α) (@perm.refl α) (@perm.symm α) (@perm.trans α)
id   └────────────┘   └──┘     └───────┘     └───────┘     └────────┘ 
src  └────────────┘   └──┘      └───────┘      └───────┘      └────────┘
typ  └────────────┘   └──┘     └───────┘     └───────┘     └────────┘ 
doc                   └──┘
 44  
 45  instance is_setoid (α) : setoid (list α) :=
id                            └────┘  └──┘ 
src                           └────┘  └──┘
typ                           └────┘  └──┘ 
 46  setoid.mk (@perm α) (perm.eqv α)
id   └───────┘   └──┘    └──────┘ 
src  └───────┘   └──┘     └──────┘
typ  └───────┘   └──┘    └──────┘ 
doc              └──┘
 47  
 48  theorem perm_subset {l₁ l₂ : list α} (p : l₁ ~ l₂) : l₁ ⊆ l₂ :=
id                                └──┘        └┘  └┘    └┘  └┘
src                               └──┘                      
typ                               └──┘        └┘  └┘    └┘  └┘
doc                                               
 49  λ a, perm.rec_on p
id       └─────────┘ 
src       └─────────┘
typ      └─────────┘ 
 50    (λ h, h)
id          
typ         
 51    (λ x l₁ l₂ p₁ r₁ i, or.elim i
id         └┘ └┘ └┘ └┘   └─────┘ 
src                        └─────┘
typ        └┘ └┘ └┘ └┘   └─────┘ 
 52      (λ ax, by simp [ax])
id          └┘           └┘
src                └────┘  
typ         └┘     └────┘└┘
doc                └────┘  
txt                └────┘  
par                └────┘  
pid                      
st                └────────┘
 53      (λ al₁, or.inr (r₁ al₁)))
id          └─┘  └────┘  └┘ └─┘
src              └────┘
typ         └─┘  └────┘  └┘ └─┘
 54    (λ x y l ayxl, or.elim ayxl
id           └──┘  └─────┘ └──┘
src                   └─────┘
typ          └──┘  └─────┘ └──┘
 55      (λ ay, by simp [ay])
id          └┘           └┘
src                └────┘  
typ         └┘     └────┘└┘
doc                └────┘  
txt                └────┘  
par                └────┘  
pid                      
st                └────────┘
 56      (λ axl, or.elim axl
id          └─┘  └─────┘ └─┘
src              └─────┘
typ         └─┘  └─────┘ └─┘
 57        (λ ax, by simp [ax])
id            └┘           └┘
src                  └────┘  
typ           └┘     └────┘└┘
doc                  └────┘  
txt                  └────┘  
par                  └────┘  
pid                        
st                  └────────┘
 58        (λ al, or.inr (or.inr al))))
id            └┘  └────┘  └────┘ └┘
src               └────┘  └────┘
typ           └┘  └────┘  └────┘ └┘
 59    (λ l₁ l₂ l₃ p₁ p₂ r₁ r₂ ainl₁, r₂ (r₁ ainl₁))
id        └┘ └┘ └┘ └┘ └┘ └┘ └┘ └───┘  └┘  └┘ └───┘
typ       └┘ └┘ └┘ └┘ └┘ └┘ └┘ └───┘  └┘  └┘ └───┘
 60  
 61  theorem mem_of_perm {a : α} {l₁ l₂ : list α} (h : l₁ ~ l₂) : a ∈ l₁ ↔ a ∈ l₂ :=
id                                       └──┘        └┘  └┘      └┘    └┘
src                                       └──┘                            
typ                                      └──┘        └┘  └┘      └┘    └┘
doc                                                       
 62  iff.intro (λ m, perm_subset h m) (λ m, perm_subset h.symm m)
id   └───────┘      └─────────┘         └─────────┘ └───┘ 
src  └───────┘       └─────────┘            └─────────┘  └───┘
typ  └───────┘      └─────────┘         └─────────┘ └───┘ 
 63  
 64  theorem perm_app_left {l₁ l₂ : list α} (t₁ : list α) (p : l₁ ~ l₂) : l₁++t₁ ~ l₂++t₁ :=
id                                  └──┘         └──┘        └┘  └┘    └┘└┘└┘  └┘└┘└┘
src                                 └──┘          └──┘                     └┘      └┘
typ                                 └──┘         └──┘        └┘  └┘    └┘└┘└┘  └┘└┘└┘
doc                                                                             
 65  perm.rec_on p
id   └─────────┘ 
src  └─────────┘
typ  └─────────┘ 
 66    (perm.refl ([] ++ t₁))
id      └───────┘  └┘ └┘ └┘
src     └───────┘  └┘ └┘
typ     └───────┘  └┘ └┘ └┘
 67    (λ x l₁ l₂ p₁ r₁, skip x r₁)
id         └┘ └┘ └┘ └┘  └──┘  └┘
src                      └──┘
typ        └┘ └┘ └┘ └┘  └──┘  └┘
 68    (λ x y l, swap x y _)
id            └──┘  
src              └──┘
typ           └──┘  
 69    (λ l₁ l₂ l₃ p₁ p₂ r₁ r₂, trans r₁ r₂)
id        └┘ └┘ └┘ └┘ └┘ └┘ └┘  └───┘ └┘ └┘
src                             └───┘
typ       └┘ └┘ └┘ └┘ └┘ └┘ └┘  └───┘ └┘ └┘
 70  
 71  theorem perm_app_right {t₁ t₂ : list α} : ∀ (l : list α), t₁ ~ t₂ → l++t₁ ~ l++t₂
id                                   └──┘           └──┘    └┘  └┘   └┘└┘  └┘└┘
src                                  └──┘             └──┘               └┘     └┘
typ                                  └──┘           └──┘    └┘  └┘   └┘└┘  └┘└┘
doc                                                                           
 72  | []      p := p
id     └┘      
src    └┘
typ    └┘      
 73  | (x::xs) p := skip x (perm_app_right xs p)
id      └┘└┘      └──┘    └────────────┘
src      └┘         └──┘
typ     └┘└┘      └──┘    └────────────┘
 74  
 75  theorem perm_app {l₁ l₂ t₁ t₂ : list α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁++t₁ ~ l₂++t₂ :=
id                                   └──┘         └┘  └┘        └┘  └┘    └┘└┘└┘  └┘└┘└┘
src                                  └──┘                                    └┘      └┘
typ                                  └──┘         └┘  └┘        └┘  └┘    └┘└┘└┘  └┘└┘└┘
doc                                                                               
 76  trans (perm_app_left t₁ p₁) (perm_app_right l₂ p₂)
id   └───┘  └───────────┘ └┘ └┘   └────────────┘ └┘ └┘
src  └───┘  └───────────┘         └────────────┘
typ  └───┘  └───────────┘ └┘ └┘   └────────────┘ └┘ └┘
 77  
 78  theorem perm_app_cons (a : α) {h₁ h₂ t₁ t₂ : list α}
id                                               └──┘ 
src                                               └──┘
typ                                              └──┘ 
 79    (p₁ : h₁ ~ h₂) (p₂ : t₁ ~ t₂) : h₁ ++ a::t₁ ~ h₂ ++ a::t₂ :=
id           └┘  └┘        └┘  └┘    └┘ └┘ └┘└┘  └┘ └┘ └┘└┘
src                                     └┘  └┘       └┘  └┘
typ          └┘  └┘        └┘  └┘    └┘ └┘ └┘└┘  └┘ └┘ └┘└┘
doc                                              
 80  perm_app p₁ (skip a p₂)
id   └──────┘ └┘  └──┘  └┘
src  └──────┘     └──┘
typ  └──────┘ └┘  └──┘  └┘
 81  
 82  @[simp] theorem perm_middle {a : α} : ∀ {l₁ l₂ : list α}, l₁++a::l₂ ~ a::(l₁++l₂)
id                                                  └──┘    └┘└┘└┘└┘  └┘ └┘└┘└┘
src                                                   └──┘       └┘ └┘     └┘   └┘
typ                                                 └──┘    └┘└┘└┘└┘  └┘ └┘└┘└┘
doc    └──┘                                                              
 83  | []      l₂ := perm.refl _
id     └┘            └───────┘
src    └┘            └───────┘
typ    └┘            └───────┘
 84  | (b::l₁) l₂ := (skip b (@perm_middle l₁ l₂)).trans (swap a b _)
id      └┘└┘  └┘     └──┘     └─────────┘        └───┘   └──┘ 
src      └┘           └──┘                        └───┘   └──┘
typ     └┘└┘  └┘     └──┘     └─────────┘        └───┘   └──┘ 
 85  
 86  @[simp] theorem perm_cons_app (a : α) (l : list α) : l ++ [a] ~ a::l :=
id                                             └──┘      └┘   └┘
src                                             └──┘        └┘     └┘
typ                                            └──┘      └┘   └┘
doc    └──┘                                                        
 87  by simpa using @perm_middle _ a l []
id                   └─────────┘     └┘
src     └──────────┘ └─────────┘└─┘  └┘
typ     └──────────┘ └─────────┘└─┘└┘
doc     └──────────┘            └─┘    
txt     └──────────┘            └─┘    
par     └──────────┘            └─┘    
pid          └────┘            └─┘    
st     └──────────────────────────────────
 88  
src  
typ  
doc  
txt  
par  
pid  
st   
 89  @[simp] theorem perm_app_comm : ∀ {l₁ l₂ : list α}, (l₁++l₂) ~ (l₂++l₁)
id                                             └──┘     └┘└┘└┘    └┘└┘└┘
src                                             └──┘        └┘        └┘
typ                                            └──┘     └┘└┘└┘    └┘└┘└┘
doc    └──┘                                                       
 90  | []     l₂ := by simp
id     └┘
src    └┘              └───┘
typ    └┘              └───┘
doc                    └───┘
txt                    └───┘
par                    └───┘
pid                        
st                    └────┘
 91  | (a::t) l₂ := (skip a perm_app_comm).trans perm_middle.symm
id      └┘          └──┘   └───────────┘ └───┘  └─────────┘└───┘
src      └┘          └──┘                 └───┘  └─────────┘└───┘
typ     └┘          └──┘   └───────────┘ └───┘  └─────────┘└───┘
 92  
 93  theorem concat_perm (l : list α) (a : α) : concat l a ~ a :: l :=
id                            └──┘            └────┘     └┘ 
src                           └──┘              └────┘        └┘
typ                           └──┘            └────┘     └┘ 
doc                                             └────┘     
 94  by simp
src     └────
typ     └────
doc     └────
txt     └────
par     └────
pid         
st     └─────
 95  
src  
typ  
doc  
txt  
par  
pid  
st   
 96  theorem perm_length {l₁ l₂ : list α} (p : l₁ ~ l₂) : length l₁ = length l₂ :=
id                                └──┘        └┘  └┘    └────┘ └┘  └────┘ └┘
src                               └──┘                   └────┘     └────┘
typ                               └──┘        └┘  └┘    └────┘ └┘  └────┘ └┘
doc                                               
 97  perm.rec_on p
id   └─────────┘ 
src  └─────────┘
typ  └─────────┘ 
 98    rfl
id     └─┘
src    └─┘
typ    └─┘
 99    (λ x l₁ l₂ p r, by simp[r])
id         └┘ └┘            
src                       └───┘ 
typ        └┘ └┘       └───┘
doc                       └───┘ 
txt                       └───┘ 
par                       └───┘ 
pid                            
st                       └──────┘
100    (λ x y l, by simp)
id          
src                 └──┘
typ              └──┘
doc                 └──┘
txt                 └──┘
par                 └──┘
st                 └───┘
101    (λ l₁ l₂ l₃ p₁ p₂ r₁ r₂, eq.trans r₁ r₂)
id        └┘ └┘ └┘ └┘ └┘ └┘ └┘  └──────┘ └┘ └┘
src                             └──────┘
typ       └┘ └┘ └┘ └┘ └┘ └┘ └┘  └──────┘ └┘ └┘
102  
103  theorem eq_nil_of_perm_nil {l₁ : list α} (p : [] ~ l₁) : l₁ = [] :=
id                                    └──┘        └┘  └┘    └┘  └┘
src                                   └──┘         └┘            └┘
typ                                   └──┘        └┘  └┘    └┘  └┘
doc                                                   
104  eq_nil_of_length_eq_zero (perm_length p).symm
id   └──────────────────────┘  └─────────┘  └──┘
src  └──────────────────────┘  └─────────┘   └──┘
typ  └──────────────────────┘  └─────────┘  └──┘
105  
106  theorem perm_nil {l₁ : list α} : l₁ ~ [] ↔ l₁ = [] :=
id                          └──┘     └┘  └┘  └┘  └┘
src                         └──┘          └┘      └┘
typ                         └──┘     └┘  └┘  └┘  └┘
doc                                      
107  ⟨λ p, eq_nil_of_perm_nil p.symm, λ e, e ▸ perm.refl _⟩
id        └────────────────┘ └───┘        └───────┘
src        └────────────────┘  └───┘          └───────┘
typ       └────────────────┘ └───┘        └───────┘
108  
109  theorem not_perm_nil_cons (x : α) (l : list α) : ¬ [] ~ x::l
id                                         └──┘      └┘  └┘
src                                         └──┘       └┘   └┘
typ                                        └──┘      └┘  └┘
doc                                                        
110  | p := by injection eq_nil_of_perm_nil p
id                       └────────────────┘ 
src            └────────┘└────────────────┘ 
typ            └────────┘└────────────────┘
doc            └────────┘                   
txt            └────────┘                   
par            └────────┘                   
pid                                        
st            └───────────────────────────────
111  
src  
typ  
doc  
txt  
par  
pid  
st   
112  theorem eq_singleton_of_perm {a b : α} (p : [a] ~ [b]) : a = b :=
id                                                      
src                                                        
typ                                                     
doc                                                  
113  by simpa using perm_subset p (by simp)
id                  └─────────┘ 
src     └──────────┘└─────────┘    └──┘└─
typ     └──────────┘└─────────┘   └──┘└─
doc     └──────────┘               └──┘└─
txt     └──────────┘               └──┘└─
par     └──────────┘               └──┘└─
pid          └────┘               └────┘
st     └────────────────────────────┘└───┘└─
114  
src  
typ  
doc  
txt  
par  
pid  
st   
115  theorem eq_singleton_of_perm_inv {a : α} {l : list α} (p : [a] ~ l) : l = [a] :=
id                                                └──┘                
src                                                └──┘                     
typ                                               └──┘                
doc                                                                 
116  match l, show 1 = _, from perm_length p, p with
id                           └─────────┘   
src                           └─────────┘
typ                          └─────────┘   
117  | [a'], rfl, p := by rw [eq_singleton_of_perm p]
id         └─┘              └──────────────────┘ 
src        └─┘          └──┘└──────────────────┘ └┘
typ        └─┘          └──┘└──────────────────┘└┘
doc                       └──┘                     └┘
txt                       └──┘                     └┘
par                       └──┘                     └┘
pid                         └┘                     
st                       └─────────────────────────┘
118  end
119  
120  @[simp] theorem reverse_perm : ∀ (l : list α), reverse l ~ l
id                                        └──┘    └─────┘   
src                                        └──┘     └─────┘   
typ                                       └──┘    └─────┘   
doc    └──┘                                                   
121  | []     := perm.nil
id     └┘        └──────┘
src    └┘        └──────┘
typ    └┘        └──────┘
122  | (a::l) := by rw reverse_cons; exact
id       └┘            └──────────┘
src      └┘         └─┘└──────────┘  └─────
typ      └┘         └─┘└──────────┘  └─────
doc                 └─┘              └─────
txt                 └─┘              └─────
par                 └─┘              └─────
pid                                      
st                 └───────────────────────
123    (perm_cons_app _ _).trans (skip a $ reverse_perm l)
id      └───────────┘             └──┘    └──────────┘ 
src  ─┘ └───────────┘└──────────┘ └──┘               └─
typ  ─┘ └───────────┘└──────────┘ └──┘ └──────────┘└─
doc  ─┘              └──────────┘                    └─
txt  ─┘              └──────────┘                    └─
par  ─┘              └──────────┘                    └─
pid  ─┘              └──────────┘                    
st   ──────────────────────────────────────────────────────
124  
src  
typ  
doc  
txt  
par  
pid  
st   
125  theorem perm_cons_app_cons {l l₁ l₂ : list α} (a : α) (p : l ~ l₁++l₂) : a::l ~ l₁++(a::l₂) :=
id                                         └──┘                 └┘└┘└┘    └┘  └┘└┘ └┘└┘
src                                        └──┘                      └┘       └┘     └┘  └┘
typ                                        └──┘                 └┘└┘└┘    └┘  └┘└┘ └┘└┘
doc                                                                               
126  trans (skip a p) perm_middle.symm
id   └───┘  └──┘    └─────────┘└───┘
src  └───┘  └──┘      └─────────┘└───┘
typ  └───┘  └──┘    └─────────┘└───┘
127  
128  @[simp] theorem perm_repeat {a : α} {n : ℕ} {l : list α} : repeat a n ~ l ↔ repeat a n = l :=
id                                                  └──┘     └────┘      └────┘    
src                                                  └──┘      └────┘         └────┘     
typ                                                 └──┘     └────┘      └────┘    
doc    └──┘                                                                
129  ⟨λ p, (eq_repeat.2 $ by exact
id         └───────┘
src         └───────┘       └─────
typ        └───────┘       └─────
doc                          └─────
txt                          └─────
par                          └─────
pid                               
st                          └──────
130    ⟨by simpa using (perm_length p).symm,
id                      └─────────┘ 
src  ─┘   └──────────┘ └─────────┘ └────┘└─
typ  ─┘   └──────────┘ └─────────┘└────┘└─
doc  ─┘   └──────────┘             └────┘└─
txt  ─┘   └──────────┘             └────┘└─
par  ─┘   └──────────┘             └────┘└─
pid  ─┘   └───────────┘             └───────
st   ────┘└───────────────────────────────┘└─
131     λ b m, eq_of_mem_repeat $ perm_subset p.symm m⟩).symm,
id             └──────────────┘   └─────────┘ └────┘    └──┘
src  ──┘ └────┘└──────────────┘ └─────────┘└────┘  └──┘
typ  ──┘ └────┘└──────────────┘ └─────────┘└────┘  └──┘
doc  ──┘ └────┘                                   
txt  ──┘ └────┘                                   
par  ──┘ └────┘                                   
pid  ──┘ └────┘                                   
st   ─────────────────────────────────────────────────┘
132   λ h, h ▸ perm.refl _⟩
id          └───────┘
src           └───────┘
typ         └───────┘
133  
134  theorem perm_erase [decidable_eq α] {a : α} {l : list α} (h : a ∈ l) : l ~ a :: l.erase a :=
id                       └──────────┘               └──┘                 └┘ └────┘ 
src                      └──────────┘                 └──┘                      └┘  └────┘
typ                      └──────────┘               └──┘                 └┘ └────┘ 
doc                                                                           
135  let ⟨l₁, l₂, _, e₁, e₂⟩ := exists_erase_eq h in
id   └─┘             └┘  └┘     └─────────────┘ 
src                             └─────────────┘
typ  └─┘             └┘  └┘     └─────────────┘ 
136  e₂.symm ▸ e₁.symm ▸ perm_middle
id     └───┘    └───┘  └─────────┘
src    └───┘    └───┘  └─────────┘
typ    └───┘    └───┘  └─────────┘
137  
138  @[elab_as_eliminator] theorem perm_induction_on
doc    └────────────────┘
139      {P : list α → list α → Prop} {l₁ l₂ : list α} (p : l₁ ~ l₂)
id            └──┘    └──┘                   └──┘        └┘  └┘
src           └──┘     └──┘                    └──┘            
typ           └──┘    └──┘                   └──┘        └┘  └┘
doc                                                            
140      (h₁ : P [] [])
id              └┘ └┘
src              └┘ └┘
typ             └┘ └┘
141      (h₂ : ∀ x l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (x::l₁) (x::l₂))
id                └┘ └┘  └┘  └┘    └┘ └┘     └┘└┘   └┘└┘
src                                              └┘      └┘
typ               └┘ └┘  └┘  └┘    └┘ └┘     └┘└┘   └┘└┘
doc                          
142      (h₃ : ∀ x y l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (y::x::l₁) (x::y::l₂))
id                 └┘ └┘  └┘  └┘    └┘ └┘     └┘└┘└┘   └┘└┘└┘
src                                                └┘ └┘      └┘ └┘
typ                └┘ └┘  └┘  └┘    └┘ └┘     └┘└┘└┘   └┘└┘└┘
doc                            
143      (h₄ : ∀ l₁ l₂ l₃, l₁ ~ l₂ → l₂ ~ l₃ → P l₁ l₂ → P l₂ l₃ → P l₁ l₃) :
id               └┘ └┘ └┘  └┘  └┘   └┘  └┘    └┘ └┘    └┘ └┘    └┘ └┘
src                                    
typ              └┘ └┘ └┘  └┘  └┘   └┘  └┘    └┘ └┘    └┘ └┘    └┘ └┘
doc                                    
144    P l₁ l₂ :=
id      └┘ └┘
typ     └┘ └┘
145  have P_refl : ∀ l, P l l, from
id                       
typ                      
146    assume l,
id            
typ           
147    list.rec_on l h₁ (λ x xs ih, h₂ x xs xs (perm.refl xs) ih),
id     └─────────┘  └┘     └┘ └┘  └┘  └┘ └┘  └───────┘ └┘  └┘
src    └─────────┘                              └───────┘
typ    └─────────┘  └┘     └┘ └┘  └┘  └┘ └┘  └───────┘ └┘  └┘
148  perm.rec_on p h₁ h₂ (λ x y l, h₃ x y l l (perm.refl l) (P_refl l)) h₄
id   └─────────┘  └┘ └┘        └┘      └───────┘    └────┘    └┘
src  └─────────┘                               └───────┘
typ  └─────────┘  └┘ └┘        └┘      └───────┘    └────┘    └┘
149  
150  @[congr] theorem perm_filter_map (f : α → option β) {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id                                            └────┘            └──┘        └┘  └┘
src    └───┘                                   └────┘             └──┘            
typ                                           └────┘            └──┘        └┘  └┘
doc    └───┘                                                                      
151    filter_map f l₁ ~ filter_map f l₂ :=
id     └────────┘  └┘  └────────┘  └┘
src    └────────┘       └────────┘
typ    └────────┘  └┘  └────────┘  └┘
doc                    
152  begin
st   └─────
153    induction p with x l₂ l₂' p IH  x y l₂  l₂ m₂ r₂ p₁ p₂ IH₁ IH₂,
id               
src    └────────┘ └─────────────────────────────────────────────────┘
typ    └────────┘└─────────────────────────────────────────────────┘
doc    └────────┘ └─────────────────────────────────────────────────┘
txt    └────────┘ └─────────────────────────────────────────────────┘
par    └────────┘ └─────────────────────────────────────────────────┘
pid              └────────────────────────────────────────────────┘
st   ───────────────────────────────────────────────────────────────┘└─
154    { simp },
src      └───┘
typ      └───┘
doc      └───┘
txt      └───┘
par      └───┘
pid          
st   ───┘└───┘└┘
155    { simp [filter_map], cases f x with a; simp [filter_map, IH, skip] },
id             └────────┘                         └────────┘  └┘  └──┘
src      └────┘└────────┘  └────┘  └─────┘  └────┘└────────┘└┘  └┘└──┘└┘
typ      └────┘└────────┘  └────┘└─────┘  └────┘└────────┘└┘└┘└┘└──┘└┘
doc      └────┘            └────┘  └─────┘  └────┘          └┘  └┘    └┘
txt      └────┘            └────┘  └─────┘  └────┘          └┘  └┘    └┘
par      └────┘            └────┘  └─────┘  └────┘          └┘  └┘    └┘
pid                             └─────┘                └┘  └┘    
st   ───┘└───────────────┘└──────────────────────────────────────────────┘└┘
156    { simp [filter_map], cases f x with a; cases f y with b; simp [filter_map, swap] },
id             └────────┘                                         └────────┘  └──┘
src      └────┘└────────┘  └────┘  └─────┘  └────┘  └─────┘  └────┘└────────┘└┘└──┘└┘
typ      └────┘└────────┘  └────┘└─────┘  └────┘└─────┘  └────┘└────────┘└┘└──┘└┘
doc      └────┘            └────┘  └─────┘  └────┘  └─────┘  └────┘          └┘    └┘
txt      └────┘            └────┘  └─────┘  └────┘  └─────┘  └────┘          └┘    └┘
par      └────┘            └────┘  └─────┘  └────┘  └─────┘  └────┘          └┘    └┘
pid                             └─────┘         └─────┘                └┘    
st   ───┘└───────────────┘└────────────────────────────────────────────────────────────┘└┘
157    { exact IH₁.trans IH₂ }
id             └───────┘ └─┘
src      └────┘└───────┘   
typ      └────┘└───────┘└─┘
doc      └────┘            
txt      └────┘            
par      └────┘            
pid                       
st   ───────────────────────┘└─
158  end
st   ──┘
159  
160  @[congr] theorem perm_map (f : α → β) {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id                                                └──┘        └┘  └┘
src    └───┘                                        └──┘            
typ                                               └──┘        └┘  └┘
doc    └───┘                                                        
161    map f l₁ ~ map f l₂ :=
id     └─┘  └┘  └─┘  └┘
src    └─┘       └─┘
typ    └─┘  └┘  └─┘  └┘
doc             
162  by rw ← filter_map_eq_map; apply perm_filter_map _ p
id           └───────────────┘        └─────────────┘   
src     └───┘└───────────────┘  └────┘└─────────────┘└─┘ 
typ     └───┘└───────────────┘  └────┘└─────────────┘└─┘
doc     └───┘                   └────┘               └─┘ 
txt     └───┘                   └────┘               └─┘ 
par     └───┘                   └────┘               └─┘ 
pid       └─┘                                       └─┘ 
st     └──────────────────────────────────────────────────
163  
src  
typ  
doc  
txt  
par  
pid  
st   
164  theorem perm_pmap {p : α → Prop} (f : Π a, p a → β)
id                                                
typ                                               
165    {l₁ l₂ : list α} (p : l₁ ~ l₂) {H₁ H₂} : pmap f l₁ H₁ ~ pmap f l₂ H₂ :=
id              └──┘        └┘  └┘            └──┘  └┘ └┘  └──┘  └┘ └┘
src             └──┘                           └──┘          └──┘
typ             └──┘        └┘  └┘            └──┘  └┘ └┘  └──┘  └┘ └┘
doc                                            └──┘          └──┘
166  begin
st   └─────
167    induction p with x l₂ l₂' p IH  x y l₂  l₂ m₂ r₂ p₁ p₂ IH₁ IH₂,
id               
src    └────────┘ └─────────────────────────────────────────────────┘
typ    └────────┘└─────────────────────────────────────────────────┘
doc    └────────┘ └─────────────────────────────────────────────────┘
txt    └────────┘ └─────────────────────────────────────────────────┘
par    └────────┘ └─────────────────────────────────────────────────┘
pid              └────────────────────────────────────────────────┘
st   ───────────────────────────────────────────────────────────────┘└─
168    { simp },
src      └───┘
typ      └───┘
doc      └───┘
txt      └───┘
par      └───┘
pid          
st   ───┘└───┘└┘
169    { simp [IH, skip] },
id                 └──┘
src      └────┘  └┘└──┘└┘
typ      └────┘└┘└┘└──┘└┘
doc      └────┘  └┘    └┘
txt      └────┘  └┘    └┘
par      └────┘  └┘    └┘
pid            └┘    
st   ───┘└──────────────┘└┘
170    { simp [swap] },
id             └──┘
src      └────┘└──┘└┘
typ      └────┘└──┘└┘
doc      └────┘    └┘
txt      └────┘    └┘
par      └────┘    └┘
pid              
st   ───┘└──────────┘└┘
171    { refine IH₁.trans IH₂,
id              └───────┘ └─┘
src      └─────┘└───────┘
typ      └─────┘└───────┘└─┘
doc      └─────┘         
txt      └─────┘         
par      └─────┘         
pid                     
st   ───────────────────────┘└─
172      exact λ a m, H₂ a (perm_subset p₂ m) }
id                    └┘    └─────────┘ └┘
src      └────┘ └────┘    └─────────┘   └┘
typ      └────┘ └────┘└┘  └─────────┘└┘ └┘
doc      └────┘ └────┘                  └┘
txt      └────┘ └────┘                  └┘
par      └────┘ └────┘                  └┘
pid            └────┘                  
st   ────────────────────────────────────────┘└─
173  end
st   ──┘
174  
175  theorem perm_filter (p : α → Prop) [decidable_pred p]
id                                      └────────────┘ 
src                                      └────────────┘
typ                                     └────────────┘ 
176    {l₁ l₂ : list α} (s : l₁ ~ l₂) : filter p l₁ ~ filter p l₂ :=
id              └──┘        └┘  └┘    └────┘  └┘  └────┘  └┘
src             └──┘                   └────┘       └────┘
typ             └──┘        └┘  └┘    └────┘  └┘  └────┘  └┘
doc                                                
177  by rw ← filter_map_eq_filter; apply perm_filter_map _ s
id           └──────────────────┘        └─────────────┘   
src     └───┘└──────────────────┘  └────┘└─────────────┘└─┘ 
typ     └───┘└──────────────────┘  └────┘└─────────────┘└─┘
doc     └───┘                      └────┘               └─┘ 
txt     └───┘                      └────┘               └─┘ 
par     └───┘                      └────┘               └─┘ 
pid       └─┘                                          └─┘ 
st     └─────────────────────────────────────────────────────
178  
src  
typ  
doc  
txt  
par  
pid  
st   
179  theorem exists_perm_sublist {l₁ l₂ l₂' : list α}
id                                            └──┘ 
src                                           └──┘
typ                                           └──┘ 
180    (s : l₁ <+ l₂) (p : l₂ ~ l₂') : ∃ l₁' ~ l₁, l₁' <+ l₂' :=
id          └┘ └┘ └┘       └┘  └─┘     └─┘   └┘ └─┘ └┘ └─┘
src            └┘                                   └┘
typ         └┘ └┘ └┘       └┘  └─┘     └─┘   └┘ └─┘ └┘ └─┘
doc                           
181  begin
st   └─────
182    induction p with x l₂ l₂' p IH  x y l₂  l₂ m₂ r₂ p₁ p₂ IH₁ IH₂ generalizing l₁ s,
id               
src    └────────┘ └───────────────────────────────────────────────────────────────────┘
typ    └────────┘└───────────────────────────────────────────────────────────────────┘
doc    └────────┘ └───────────────────────────────────────────────────────────────────┘
txt    └────────┘ └───────────────────────────────────────────────────────────────────┘
par    └────────┘ └───────────────────────────────────────────────────────────────────┘
pid              └────────────────────────────────────────────────┘└────────────────┘
st   ─────────────────────────────────────────────────────────────────────────────────┘└─
183    { exact ⟨[], eq_nil_of_sublist_nil s ▸ perm.refl _, nil_sublist _⟩ },
id                  └───────────────────┘   └───────┘    └─────────┘
src      └────┘   └┘└───────────────────┘ └───────┘└──┘└─────────┘└──┘
typ      └────┘   └┘└───────────────────┘└───────┘└──┘└─────────┘└──┘
doc      └────┘   └┘                                └──┘           └──┘
txt      └────┘   └┘                                └──┘           └──┘
par      └────┘   └┘                                └──┘           └──┘
pid              └┘                                └──┘           └─┘
st   ───┘└───────────────────────────────────────────────────────────────┘└┘
184    { cases s with _ _ _ s l₁ _ _ s,
id             
src      └────┘ └────────────────────┘
typ      └────┘└────────────────────┘
doc      └────┘ └────────────────────┘
txt      └────┘ └────────────────────┘
par      └────┘ └────────────────────┘
pid            └────────────────────┘
st   ───┘└───────────────────────────┘└─
185      { exact let ⟨l₁', p', s'⟩ := IH s in ⟨l₁', p', s'.cons _ _ _⟩ },
id                    └─┘  └┘  └┘     └┘                 └───┘
src        └────┘       └┘  └┘  └───┘   └──┘    └┘  └┘  └───┘└──────┘
typ        └────┘    └─┘└┘└┘└┘└┘└───┘└┘└──┘    └┘  └┘  └───┘└──────┘
doc        └────┘       └┘  └┘  └───┘   └──┘    └┘  └┘       └──────┘
txt        └────┘       └┘  └┘  └───┘   └──┘    └┘  └┘       └──────┘
par        └────┘       └┘  └┘  └───┘   └──┘    └┘  └┘       └──────┘
pid                    └┘  └┘  └───┘   └──┘    └┘  └┘       └─────┘
st   ─────┘└──────────────────────────────────────────────────────────┘└┘
186      { exact let ⟨l₁', p', s'⟩ := IH s in ⟨x::l₁', skip x p', s'.cons2 _ _ _⟩ } },
id                    └─┘  └┘  └┘     └┘              └──┘        └────┘
src        └────┘       └┘  └┘  └───┘   └──┘       └┘└──┘   └┘  └────┘└──────┘
typ        └────┘    └─┘└┘└┘└┘└┘└───┘└┘└──┘       └┘└──┘  └┘  └────┘└──────┘
doc        └────┘       └┘  └┘  └───┘   └──┘       └┘       └┘        └──────┘
txt        └────┘       └┘  └┘  └───┘   └──┘       └┘       └┘        └──────┘
par        └────┘       └┘  └┘  └───┘   └──┘       └┘       └┘        └──────┘
pid                    └┘  └┘  └───┘   └──┘       └┘       └┘        └─────┘
st   ────────────────────────────────────────────────────────────────────────────┘└──┘
187    { cases s with _ _ _ s l₁ _ _ s; cases s with _ _ _ s l₁ _ _ s,
id                                           
src      └────┘ └────────────────────┘  └────┘ └────────────────────┘
typ      └────┘└────────────────────┘  └────┘└────────────────────┘
doc      └────┘ └────────────────────┘  └────┘ └────────────────────┘
txt      └────┘ └────────────────────┘  └────┘ └────────────────────┘
par      └────┘ └────────────────────┘  └────┘ └────────────────────┘
pid            └────────────────────┘        └────────────────────┘
st   ───┘└──────────────────────────────────────────────────────────┘└─
188      { exact ⟨l₁, perm.refl _, (s.cons _ _ _).cons _ _ _⟩ },
id                └┘  └───────┘     └────┘
src        └────┘   └┘└───────┘└──┘ └────┘└──────────────────┘
typ        └────┘ └┘└┘└───────┘└──┘ └────┘└──────────────────┘
doc        └────┘   └┘         └──┘       └──────────────────┘
txt        └────┘   └┘         └──┘       └──────────────────┘
par        └────┘   └┘         └──┘       └──────────────────┘
pid                └┘         └──┘       └─────────────────┘
st   ─────┘└─────────────────────────────────────────────────┘└┘
189      { exact ⟨x::l₁, perm.refl _, (s.cons _ _ _).cons2 _ _ _⟩ },
id                  └┘  └───────┘     └────┘
src        └────┘      └┘└───────┘└──┘ └────┘└───────────────────┘
typ        └────┘   └┘└┘└───────┘└──┘ └────┘└───────────────────┘
doc        └────┘      └┘         └──┘       └───────────────────┘
txt        └────┘      └┘         └──┘       └───────────────────┘
par        └────┘      └┘         └──┘       └───────────────────┘
pid                   └┘         └──┘       └──────────────────┘
st   ─────┘└─────────────────────────────────────────────────────┘└┘
190      { exact ⟨y::l₁, perm.refl _, (s.cons2 _ _ _).cons _ _ _⟩ },
id                  └┘  └───────┘     └─────┘
src        └────┘      └┘└───────┘└──┘ └─────┘└──────────────────┘
typ        └────┘   └┘└┘└───────┘└──┘ └─────┘└──────────────────┘
doc        └────┘      └┘         └──┘        └──────────────────┘
txt        └────┘      └┘         └──┘        └──────────────────┘
par        └────┘      └┘         └──┘        └──────────────────┘
pid                   └┘         └──┘        └─────────────────┘
st   ─────┘└─────────────────────────────────────────────────────┘└┘
191      { exact ⟨x::y::l₁, perm.swap _ _ _, (s.cons2 _ _ _).cons2 _ _ _⟩ } },
id                    └┘  └───────┘         └─────┘
src        └────┘         └┘└───────┘└──────┘ └─────┘└───────────────────┘
typ        └────┘     └┘└┘└───────┘└──────┘ └─────┘└───────────────────┘
doc        └────┘         └┘         └──────┘        └───────────────────┘
txt        └────┘         └┘         └──────┘        └───────────────────┘
par        └────┘         └┘         └──────┘        └───────────────────┘
pid                      └┘         └──────┘        └──────────────────┘
st   ────────────────────────────────────────────────────────────────────┘└──┘
192    { exact let ⟨m₁, pm, sm⟩ := IH₁ s, ⟨r₁, pr, sr⟩ := IH₂ sm in
id                      └┘  └┘     └─┘    └┘  └┘  └┘     └─┘
src      └────┘      └┘  └┘  └───┘    └┘   └┘  └┘  └───┘     └───
typ      └────┘      └┘└┘└┘└┘└───┘└─┘└┘ └┘└┘└┘└┘└┘└───┘└─┘  └───
doc      └────┘      └┘  └┘  └───┘    └┘   └┘  └┘  └───┘     └───
txt      └────┘      └┘  └┘  └───┘    └┘   └┘  └┘  └───┘     └───
par      └────┘      └┘  └┘  └───┘    └┘   └┘  └┘  └───┘     └───
pid                 └┘  └┘  └───┘    └┘   └┘  └┘  └───┘     └───
st   ───────────────────────────────────────────────────────────────
193            ⟨r₁, pr.trans pm, sr⟩ }
id                    └────┘
src  ─────────┘   └┘  └────┘  └┘  └┘
typ  ─────────┘   └┘  └────┘  └┘  └┘
doc  ─────────┘   └┘          └┘  └┘
txt  ─────────┘   └┘          └┘  └┘
par  ─────────┘   └┘          └┘  └┘
pid  ─────────┘   └┘          └┘  
st   ───────────────────────────────┘└─
194  end
st   ──┘
195  
196  section rel
197  open relator
198  variables {γ : Type*} {δ : Type*} {r : α → β → Prop} {p : γ → δ → Prop}
199  
200  local infixr ` ∘r ` : 80 := relation.comp
id                               └───────────┘
src                              └───────────┘
typ                              └───────────┘
201  
202  lemma perm_comp_perm : (perm ∘r perm : list α → list α → Prop) = perm :=
id                           └──┘ └┘ └──┘   └──┘    └──┘           └──┘
src                          └──┘ └┘ └──┘   └──┘     └──┘            └──┘
typ                          └──┘ └┘ └──┘   └──┘    └──┘           └──┘
doc                          └──┘    └──┘                             └──┘
203  begin
st   └─────
204    funext a c, apply propext,
id                       └─────┘
src    └────────┘  └────┘└─────┘
typ    └────────┘  └────┘└─────┘
doc    └────────┘  └────┘
txt    └────────┘  └────┘
par    └────────┘  └────┘
pid          └──┘       
st   ───────────┘└─────────────┘└─
205    split,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
st   ──────┘└─
206    { exact assume ⟨b, hab, hba⟩, perm.trans hab hba },
id                        └─┘  └─┘   └────────┘
src      └────┘      └┘ └┘   └┘   └─┘└────────┘      
typ      └────┘      └┘ └┘└─┘└┘└─┘└─┘└────────┘      
doc      └────┘      └┘ └┘   └┘   └─┘                
txt      └────┘      └┘ └┘   └┘   └─┘                
par      └────┘      └┘ └┘   └┘   └─┘                
pid                 └┘ └┘   └┘   └─┘                
st   ───┘└─────────────────────────────────────────────┘└┘
207    { exact assume h, ⟨a, perm.refl a, h⟩ }
id                           └───────┘ 
src      └────┘      └──┘  └┘└───────┘ └┘ └┘
typ      └────┘      └──┘  └┘└───────┘└┘ └┘
doc      └────┘      └──┘  └┘          └┘ └┘
txt      └────┘      └──┘  └┘          └┘ └┘
par      └────┘      └──┘  └┘          └┘ └┘
pid                 └──┘  └┘          └┘ 
st   ───────────────────────────────────────┘└─
208  end
st   ──┘
209  
210  lemma perm_comp_forall₂ {l u v} (hlu : perm l u) (huv : forall₂ r u v) : (forall₂ r ∘r perm) l v :=
id                                          └──┘           └─────┘        └─────┘  └┘ └──┘   
src                                         └──┘             └─────┘           └─────┘   └┘ └──┘
typ                                         └──┘           └─────┘        └─────┘  └┘ └──┘   
doc                                         └──┘                                            └──┘
211  begin
st   └─────
212    induction hlu generalizing v,
id               └─┘
src    └────────┘   └─────────────┘
typ    └────────┘└─┘└─────────────┘
doc    └────────┘   └─────────────┘
txt    └────────┘   └─────────────┘
par    └────────┘   └─────────────┘
pid                └────────────┘
st   ─────────────────────────────┘└─
213    case perm.nil { cases huv, exact ⟨[], forall₂.nil, perm.nil⟩ },
id                           └─┘             └─────────┘  └──────┘
src    └──────────────┘└────┘   └┘└────┘   └┘└─────────┘└┘└──────┘└┘
typ    └──────────────┘└────┘└─┘└┘└────┘   └┘└─────────┘└┘└──────┘└┘
doc    └──────────────┘└────┘   └┘└────┘   └┘           └┘        └┘
txt    └──────────────┘└────┘   └┘└────┘   └┘           └┘        └┘
par    └──────────────┘└────┘   └┘└────┘   └┘           └┘        └┘
pid        └───────┘└──────┘   └──────┘   └┘           └┘        └─┘
st   ────────────────┘└────────┘└──────────────────────────────────┘└┘
214    case perm.skip : a l u hlu ih {
src    └───────────────────────────────
typ    └───────────────────────────────
doc    └───────────────────────────────
txt    └───────────────────────────────
par    └───────────────────────────────
pid        └────────┘└─────────────┘└──
st   ────────────────────────────────┘
215      cases huv with _ b _ v hab huv',
id             └─┘
src  ───┘└────┘   └────────────────────┘└─
typ  ───┘└────┘└─┘└────────────────────┘└─
doc  ───┘└────┘   └────────────────────┘└─
txt  ───┘└────┘   └────────────────────┘└─
par  ───┘└────┘   └────────────────────┘└─
pid  ─────────┘   └───────────────────────
st   ──────────────────────────────────┘└─
216      rcases ih huv' with ⟨l₂, h₁₂, h₂₃⟩,
id              └┘ └──┘
src  ───┘└─────┘      └──────────────────┘└─
typ  ───┘└─────┘└┘└──┘└──────────────────┘└─
doc  ───┘└─────┘      └──────────────────┘└─
txt  ───┘└─────┘      └──────────────────┘└─
par  ───┘└─────┘      └──────────────────┘└─
pid  ──────────┘      └─────────────────────
st   ─────────────────────────────────────┘└─
217      exact ⟨b::l₂, forall₂.cons hab h₁₂, perm.skip _ h₂₃⟩
id                └┘  └──────────┘ └─┘ └─┘  └───────┘   └─┘
src  ───┘└────┘      └┘└──────────┘      └┘└───────┘└─┘   └─
typ  ───┘└────┘   └┘└┘└──────────┘└─┘└─┘└┘└───────┘└─┘└─┘└─
doc  ───┘└────┘      └┘                  └┘         └─┘   └─
txt  ───┘└────┘      └┘                  └┘         └─┘   └─
par  ───┘└────┘      └┘                  └┘         └─┘   └─
pid  ─────────┘      └┘                  └┘         └─┘   └─
st   ─────────────────────────────────────────────────────────
218    },
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ──┘
st   ─┘└┘
219    case perm.swap : a₁ a₂ l₁ l₂ h₂₃ {
src    └──────────────────────────────────
typ    └──────────────────────────────────
doc    └──────────────────────────────────
txt    └──────────────────────────────────
par    └──────────────────────────────────
pid        └────────┘└────────────────┘└──
st   ───────────────────────────────────┘
220      cases h₂₃ with _ b₁ _ l₂ h₁ hr_₂₃,
id             └─┘
src  ───┘└────┘   └──────────────────────┘└─
typ  ───┘└────┘└─┘└──────────────────────┘└─
doc  ───┘└────┘   └──────────────────────┘└─
txt  ───┘└────┘   └──────────────────────┘└─
par  ───┘└────┘   └──────────────────────┘└─
pid  ─────────┘   └─────────────────────────
st   ────────────────────────────────────┘└─
221      cases hr_₂₃ with _ b₂ _ l₂ h₂ h₁₂,
id             └───┘
src  ───┘└────┘     └────────────────────┘└─
typ  ───┘└────┘└───┘└────────────────────┘└─
doc  ───┘└────┘     └────────────────────┘└─
txt  ───┘└────┘     └────────────────────┘└─
par  ───┘└────┘     └────────────────────┘└─
pid  ─────────┘     └───────────────────────
st   ────────────────────────────────────┘└─
222      exact ⟨b₂::b₁::l₂, forall₂.cons h₂ (forall₂.cons h₁ h₁₂), perm.swap _ _ _⟩
id              └┘  └┘  └┘               └┘  └──────────┘ └┘ └─┘   └───────┘
src  ───┘└────┘           └┘               └──────────┘     └─┘└───────┘└───────
typ  ───┘└────┘ └┘  └┘  └┘└┘            └┘ └──────────┘└┘└─┘└─┘└───────┘└───────
doc  ───┘└────┘           └┘                                └─┘         └───────
txt  ───┘└────┘           └┘                                └─┘         └───────
par  ───┘└────┘           └┘                                └─┘         └───────
pid  ─────────┘           └┘                                └─┘         └───────
st   ───────────────────────────────────────────────────────────────────────────────
223    },
src  ─┘
typ  ─┘
doc  ─┘
txt  ─┘
par  ─┘
pid  ──┘
st   ─┘└┘
224    case perm.trans : la₁ la₂ la₃ _ _ ih₁ ih₂ {
src    └───────────────────────────────────────────
typ    └───────────────────────────────────────────
doc    └───────────────────────────────────────────
txt    └───────────────────────────────────────────
par    └───────────────────────────────────────────
pid        └─────────┘└────────────────────────┘└──
st   ────────────────────────────────────────────┘
225      rcases ih₂ huv with ⟨lb₂, hab₂, h₂₃⟩,
id              └─┘ └─┘
src  ───┘└─────┘      └────────────────────┘└─
typ  ───┘└─────┘└─┘└─┘└────────────────────┘└─
doc  ───┘└─────┘      └────────────────────┘└─
txt  ───┘└─────┘      └────────────────────┘└─
par  ───┘└─────┘      └────────────────────┘└─
pid  ──────────┘      └───────────────────────
st   ───────────────────────────────────────┘└─
226      rcases ih₁ hab₂ with ⟨lb₁, hab₁, h₁₂⟩,
id              └─┘ └──┘
src  ───┘└─────┘       └────────────────────┘└─
typ  ───┘└─────┘└─┘└──┘└────────────────────┘└─
doc  ───┘└─────┘       └────────────────────┘└─
txt  ───┘└─────┘       └────────────────────┘└─
par  ───┘└─────┘       └────────────────────┘└─
pid  ──────────┘       └───────────────────────
st   ────────────────────────────────────────┘└─
227      exact ⟨lb₁, hab₁, perm.trans h₁₂ h₂₃⟩
id              └─┘  └──┘  └────────┘ └─┘ └─┘
src  ───┘└────┘    └┘    └┘└────────┘      └─
typ  ───┘└────┘ └─┘└┘└──┘└┘└────────┘└─┘└─┘└─
doc  ───┘└────┘    └┘    └┘                └─
txt  ───┘└────┘    └┘    └┘                └─
par  ───┘└────┘    └┘    └┘                └─
pid  ─────────┘    └┘    └┘                └─
st   ──────────────────────────────────────────
228    }
src  ─┘└┘
typ  ─┘└┘
doc  ─┘└┘
txt  ─┘└┘
par  ─┘└┘
pid  ──┘
st   ─┘
229  end
st   └─┘
230  
231  lemma forall₂_comp_perm_eq_perm_comp_forall₂ : forall₂ r ∘r perm = perm ∘r forall₂ r :=
id                                                  └─────┘  └┘ └──┘  └──┘ └┘ └─────┘ 
src                                                 └─────┘   └┘ └──┘  └──┘ └┘ └─────┘
typ                                                 └─────┘  └┘ └──┘  └──┘ └┘ └─────┘ 
doc                                                              └──┘   └──┘
232  begin
st   └─────
233    funext l₁ l₃, apply propext,
id                         └─────┘
src    └──────────┘  └────┘└─────┘
typ    └──────────┘  └────┘└─────┘
doc    └──────────┘  └────┘
txt    └──────────┘  └────┘
par    └──────────┘  └────┘
pid          └────┘       
st   ─────────────┘└─────────────┘└─
234    split,
src    └───┘
typ    └───┘
doc    └───┘
txt    └───┘
par    └───┘
st   ──────┘└─
235    { assume h, rcases h with ⟨l₂, h₁₂, h₂₃⟩,
id                        
src      └──────┘  └─────┘ └──────────────────┘
typ      └──────┘  └─────┘└──────────────────┘
doc      └──────┘  └─────┘ └──────────────────┘
txt      └──────┘  └─────┘ └──────────────────┘
par      └──────┘  └─────┘ └──────────────────┘
pid      └──────┘         └──────────────────┘
st   ───┘└──────┘└────────────────────────────┘└─
236      have : forall₂ (flip r) l₂ l₁, from h₁₂.flip ,
id              └─────┘  └──┘   └┘ └┘       └──────┘
src      └─────┘└─────┘ └──┘ └┘      └───┘└──────┘
typ      └─────┘└─────┘ └──┘└┘└┘└┘  └───┘└──────┘
doc      └─────┘             └┘      └───┘        
txt      └─────┘             └┘      └───┘        
par      └─────┘             └┘      └───┘        
pid      └───┘└┘             └┘      └───┘        
st   ────────────────────────────────┘└──────────────┘└─
237      rcases perm_comp_forall₂ h₂₃.symm this with ⟨l', h₁, h₂⟩,
id              └───────────────┘ └──────┘ └──┘
src      └─────┘└───────────────┘└──────┘    └────────────────┘
typ      └─────┘└───────────────┘└──────┘└──┘└────────────────┘
doc      └─────┘                             └────────────────┘
txt      └─────┘                             └────────────────┘
par      └─────┘                             └────────────────┘
pid                                         └────────────────┘
st   ───────────────────────────────────────────────────────────┘└─
238      exact ⟨l', h₂.symm, h₁.flip⟩ },
id              └┘  └─────┘  └─────┘
src      └────┘   └┘└─────┘└┘└─────┘└┘
typ      └────┘ └┘└┘└─────┘└┘└─────┘└┘
doc      └────┘   └┘       └┘       └┘
txt      └────┘   └┘       └┘       └┘
par      └────┘   └┘       └┘       └┘
pid              └┘       └┘       
st   ────────────────────────────────┘└┘
239    { exact assume ⟨l₂, h₁₂, h₂₃⟩, perm_comp_forall₂ h₁₂ h₂₃ }
id                         └─┘  └─┘   └───────────────┘
src      └────┘      └┘  └┘   └┘   └─┘└───────────────┘      
typ      └────┘      └┘  └┘└─┘└┘└─┘└─┘└───────────────┘      
doc      └────┘      └┘  └┘   └┘   └─┘                       
txt      └────┘      └┘  └┘   └┘   └─┘                       
par      └────┘      └┘  └┘   └┘   └─┘                       
pid                 └┘  └┘   └┘   └─┘                       
st   ──────────────────────────────────────────────────────────┘└─
240  end
st   ──┘
241  
242  lemma rel_perm_imp (hr : right_unique r) : (forall₂ r ⇒ forall₂ r ⇒ implies) perm perm :=
id                            └──────────┘      └─────┘   └─────┘   └─────┘  └──┘ └──┘
src                           └──────────┘       └─────┘    └─────┘    └─────┘  └──┘ └──┘
typ                           └──────────┘      └─────┘   └─────┘   └─────┘  └──┘ └──┘
doc                                                                               └──┘ └──┘
243  assume a b h₁ c d h₂ h,
id            └┘   └┘ 
typ           └┘   └┘ 
244  have (flip (forall₂ r) ∘r (perm ∘r forall₂ r)) b d, from ⟨a, h₁, c, h, h₂⟩,
id         └──┘  └─────┘   └┘  └──┘ └┘ └─────┘               └┘      └┘
src        └──┘  └─────┘    └┘  └──┘ └┘ └─────┘
typ        └──┘  └─────┘   └┘  └──┘ └┘ └─────┘               └┘      └┘
doc                             └──┘
245  have ((flip (forall₂ r) ∘r forall₂ r) ∘r perm) b d,
id          └──┘  └─────┘   └┘ └─────┘   └┘ └──┘   
src         └──┘  └─────┘    └┘ └─────┘    └┘ └──┘
typ         └──┘  └─────┘   └┘ └─────┘   └┘ └──┘   
doc                                           └──┘
246    by rwa [← forall₂_comp_perm_eq_perm_comp_forall₂, ← relation.comp_assoc] at this,
id               └────────────────────────────────────┘    └─────────────────┘
src       └─────┘└────────────────────────────────────┘└──┘└─────────────────┘└───────┘
typ       └─────┘└────────────────────────────────────┘└──┘└─────────────────┘└───────┘
doc       └─────┘                                      └──┘                   └───────┘
txt       └─────┘                                      └──┘                   └───────┘
par       └─────┘                                      └──┘                   └───────┘
pid          └──┘                                      └──┘                   └──────┘
st       └────────────────────────────────────────────┘└─────────────────────┘└──────┘
247  let ⟨b', ⟨c', hbc, hcb⟩, hbd⟩ := this in
id   └─┘  └┘       └─┘  └─┘   └─┘     └──┘
typ  └─┘  └┘       └─┘  └─┘   └─┘     └──┘
248  have b' = b, from right_unique_forall₂ @hr hcb hbc,
id                   └──────────────────┘  └┘
src                   └──────────────────┘
typ                  └──────────────────┘  └┘
249  this ▸ hbd
id   └──┘ 
src       
typ  └──┘ 
250  
251  lemma rel_perm (hr : bi_unique r) : (forall₂ r ⇒ forall₂ r ⇒ (↔)) perm perm :=
id                        └───────┘      └─────┘   └─────┘       └──┘ └──┘
src                       └───────┘       └─────┘    └─────┘        └──┘ └──┘
typ                       └───────┘      └─────┘   └─────┘       └──┘ └──┘
doc                                                                    └──┘ └──┘
252  assume a b hab c d hcd, iff.intro
id            └─┘   └─┘  └───────┘
src                          └───────┘
typ           └─┘   └─┘  └───────┘
253    (rel_perm_imp hr.2 hab hcd)
id      └──────────┘ └┘  └─┘ └─┘
src     └──────────┘   
typ     └──────────┘ └┘  └─┘ └─┘
254    (rel_perm_imp (assume a b c, left_unique_flip hr.1) hab.flip hcd.flip)
id      └──────────┘             └──────────────┘ └┘   └─┘└───┘ └─┘└───┘
src     └──────────┘                └──────────────┘         └───┘    └───┘
typ     └──────────┘             └──────────────┘ └┘   └─┘└───┘ └─┘└───┘
255  
256  end rel
257  
258  section subperm
259  
260  /-- `subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
261    a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
262    multiplicities of elements, and is used for the `≤` relation on multisets. -/
263  def subperm (l₁ l₂ : list α) : Prop := ∃ l ~ l₁, l <+ l₂
id                        └──┘                 └┘  └┘ └┘
src                       └──┘                        └┘
typ                       └──┘                 └┘  └┘ └┘
264  
265  infix ` <+~ `:50 := subperm
id                       └─────┘
src                      └─────┘
typ                      └─────┘
doc                      └─────┘
266  
267  theorem nil_subperm {l : list α} : [] <+~ l :=
id                            └──┘     └┘ └─┘ 
src                           └──┘      └┘ └─┘
typ                           └──┘     └┘ └─┘ 
doc                                        └─┘
268  ⟨[], perm.nil, by simp⟩
id    └┘  └──────┘
src   └┘  └──────┘     └──┘
typ   └┘  └──────┘     └──┘
doc                    └──┘
txt                    └──┘
par                    └──┘
st                    └───┘
269  
270  theorem perm.subperm_left {l l₁ l₂ : list α} (p : l₁ ~ l₂) : l <+~ l₁ ↔ l <+~ l₂ :=
id                                        └──┘        └┘  └┘     └─┘ └┘   └─┘ └┘
src                                       └──┘                     └─┘       └─┘
typ                                       └──┘        └┘  └┘     └─┘ └┘   └─┘ └┘
doc                                                                └─┘        └─┘
271  suffices ∀ {l₁ l₂ : list α}, l₁ ~ l₂ → l <+~ l₁ → l <+~ l₂,
id                       └──┘    └┘  └┘    └─┘ └┘    └─┘ └┘
src                      └──┘                └─┘        └─┘
typ                      └──┘    └┘  └┘    └─┘ └┘    └─┘ └┘
doc                                          └─┘        └─┘
272  from ⟨this p, this p.symm⟩,
id         └──┘   └──┘ └───┘
src                      └───┘
typ        └──┘   └──┘ └───┘
273  λ l₁ l₂ p ⟨u, pu, su⟩,
id     └┘ └┘     └┘  └┘
typ    └┘ └┘     └┘  └┘
274    let ⟨v, pv, sv⟩ := exists_perm_sublist su p in
id     └─┘    └┘  └┘     └─────────────────┘    
src                       └─────────────────┘
typ    └─┘    └┘  └┘     └─────────────────┘    
275    ⟨v, pv.trans pu, sv⟩
id           └────┘
src          └────┘
typ          └────┘
276  
277  theorem perm.subperm_right {l₁ l₂ l : list α} (p : l₁ ~ l₂) : l₁ <+~ l ↔ l₂ <+~ l :=
id                                         └──┘        └┘  └┘    └┘ └─┘   └┘ └─┘ 
src                                        └──┘                      └─┘       └─┘
typ                                        └──┘        └┘  └┘    └┘ └─┘   └┘ └─┘ 
doc                                                                  └─┘        └─┘
278  ⟨λ ⟨u, pu, su⟩, ⟨u, pu.trans p, su⟩,
id        └┘  └┘         └────┘ 
src                        └────┘
typ       └┘  └┘         └────┘ 
279   λ ⟨u, pu, su⟩, ⟨u, pu.trans p.symm, su⟩⟩
id        └┘  └┘         └────┘ └───┘
src                        └────┘  └───┘
typ       └┘  └┘         └────┘ └───┘
280  
281  theorem subperm_of_sublist {l₁ l₂ : list α} (s : l₁ <+ l₂) : l₁ <+~ l₂ :=
id                                       └──┘        └┘ └┘ └┘    └┘ └─┘ └┘
src                                      └──┘            └┘          └─┘
typ                                      └──┘        └┘ └┘ └┘    └┘ └─┘ └┘
doc                                                                  └─┘
282  ⟨l₁, perm.refl _, s⟩
id    └┘  └───────┘    
src       └───────┘
typ   └┘  └───────┘    
283  
284  theorem subperm_of_perm {l₁ l₂ : list α} (p : l₁ ~ l₂) : l₁ <+~ l₂ :=
id                                    └──┘        └┘  └┘    └┘ └─┘ └┘
src                                   └──┘                      └─┘
typ                                   └──┘        └┘  └┘    └┘ └─┘ └┘
doc                                                             └─┘
285  ⟨l₂, p.symm, sublist.refl _⟩
id    └┘  └───┘  └──────────┘
src        └───┘  └──────────┘
typ   └┘  └───┘  └──────────┘
286  
287  theorem subperm.refl (l : list α) : l <+~ l := subperm_of_perm (perm.refl _)
id                             └──┘      └─┘     └─────────────┘  └───────┘
src                            └──┘        └─┘      └─────────────┘  └───────┘
typ                            └──┘      └─┘     └─────────────┘  └───────┘
doc                                        └─┘
288  
289  theorem subperm.trans {l₁ l₂ l₃ : list α} : l₁ <+~ l₂ → l₂ <+~ l₃ → l₁ <+~ l₃
id                                     └──┘     └┘ └─┘ └┘  └┘ └─┘ └┘   └┘ └─┘ └┘
src                                    └──┘         └─┘         └─┘         └─┘
typ                                    └──┘     └┘ └─┘ └┘  └┘ └─┘ └┘   └┘ └─┘ └┘
doc                                                 └─┘         └─┘         └─┘
290  | s ⟨l₂', p₂, s₂⟩ :=
id            └┘  └┘
typ           └┘  └┘
291    let ⟨l₁', p₁, s₁⟩ := p₂.subperm_left.2 s in ⟨l₁', p₁, s₁.trans s₂⟩
id     └─┘  └─┘  └┘  └┘       └───────────┘                   └────┘
src                           └───────────┘                   └────┘
typ    └─┘  └─┘  └┘  └┘       └───────────┘                   └────┘
292  
293  theorem length_le_of_subperm {l₁ l₂ : list α} : l₁ <+~ l₂ → length l₁ ≤ length l₂
id                                         └──┘     └┘ └─┘ └┘  └────┘ └┘  └────┘ └┘
src                                        └──┘         └─┘      └────┘     └────┘
typ                                        └──┘     └┘ └─┘ └┘  └────┘ └┘  └────┘ └┘
doc                                                     └─┘
294  | ⟨l, p, s⟩ := perm_length p ▸ length_le_of_sublist s
id                └─────────┘    └──────────────────┘
src                 └─────────┘    └──────────────────┘
typ               └─────────┘    └──────────────────┘
295  
296  theorem subperm.perm_of_length_le {l₁ l₂ : list α} : l₁ <+~ l₂ → length l₂ ≤ length l₁ → l₁ ~ l₂
id                                              └──┘     └┘ └─┘ └┘  └────┘ └┘  └────┘ └┘   └┘  └┘
src                                             └──┘         └─┘      └────┘     └────┘         
typ                                             └──┘     └┘ └─┘ └┘  └────┘ └┘  └────┘ └┘   └┘  └┘
doc                                                          └─┘                                 
297  | ⟨l, p, s⟩ h :=
id            
typ           
298    suffices l = l₂, from this ▸ p.symm,
id                 └┘       └──┘   └───┘
src                                └───┘
typ                └┘       └──┘   └───┘
299    eq_of_sublist_of_length_le s $ perm_length p.symm ▸ h
id     └────────────────────────┘     └─────────┘  └───┘ 
src    └────────────────────────┘     └─────────┘  └───┘ 
typ    └────────────────────────┘     └─────────┘  └───┘ 
300  
301  theorem subperm.antisymm {l₁ l₂ : list α} (h₁ : l₁ <+~ l₂) (h₂ : l₂ <+~ l₁) : l₁ ~ l₂ :=
id                                     └──┘         └┘ └─┘ └┘        └┘ └─┘ └┘    └┘  └┘
src                                    └──┘             └─┘              └─┘          
typ                                    └──┘         └┘ └─┘ └┘        └┘ └─┘ └┘    └┘  └┘
doc                                                     └─┘              └─┘          
302  h₁.perm_of_length_le (length_le_of_subperm h₂)
id   └┘└────────────────┘  └──────────────────┘ └┘
src    └────────────────┘  └──────────────────┘
typ  └┘└────────────────┘  └──────────────────┘ └┘
303  
304  theorem subset_of_subperm {l₁ l₂ : list α} : l₁ <+~ l₂ → l₁ ⊆ l₂
id                                      └──┘     └┘ └─┘ └┘  └┘  └┘
src                                     └──┘         └─┘         
typ                                     └──┘     └┘ └─┘ └┘  └┘  └┘
doc                                                  └─┘
305  | ⟨l, p, s⟩ := subset.trans (perm_subset p.symm) (subset_of_sublist s)
id                └──────────┘  └─────────┘  └───┘   └───────────────┘
src                 └──────────┘  └─────────┘  └───┘   └───────────────┘
typ               └──────────┘  └─────────┘  └───┘   └───────────────┘
306  
307  end subperm
308  
309  theorem exists_perm_append_of_sublist : ∀ {l₁ l₂ : list α}, l₁ <+ l₂ → ∃ l, l₂ ~ l₁ ++ l
id                                                     └──┘    └┘ └┘ └┘     └┘  └┘ └┘ 
src                                                     └──┘        └┘                └┘
typ                                                    └──┘    └┘ └┘ └┘     └┘  └┘ └┘ 
doc                                                                                 
310  | ._ ._ sublist.slnil            := ⟨nil, perm.refl _⟩
id           └───────────┘                └─┘  └───────┘
src          └───────────┘                └─┘  └───────┘
typ          └───────────┘                └─┘  └───────┘
311  | ._ ._ (sublist.cons l₁ l₂ a s) :=
id            └──────────┘        
src           └──────────┘
typ           └──────────┘        
312    let ⟨l, p⟩ := exists_perm_append_of_sublist s in
id     └─┘         └───────────────────────────┘
typ    └─┘         └───────────────────────────┘
313    ⟨a::l, (skip a p).trans perm_middle.symm⟩
id       └┘    └──┘     └───┘  └─────────┘└───┘
src      └┘    └──┘     └───┘  └─────────┘└───┘
typ      └┘    └──┘     └───┘  └─────────┘└───┘
314  | ._ ._ (sublist.cons2 l₁ l₂ a s) :=
id            └───────────┘        
src           └───────────┘
typ           └───────────┘        
315    let ⟨l, p⟩ := exists_perm_append_of_sublist s in
id     └─┘         └───────────────────────────┘
typ    └─┘         └───────────────────────────┘
316    ⟨l, skip a p⟩
id         └──┘
src        └──┘
typ        └──┘
317  
318  theorem perm_countp (p : α → Prop) [decidable_pred p]
id                                      └────────────┘ 
src                                      └────────────┘
typ                                     └────────────┘ 
319    {l₁ l₂ : list α} (s : l₁ ~ l₂) : countp p l₁ = countp p l₂ :=
id              └──┘        └┘  └┘    └────┘  └┘  └────┘  └┘
src             └──┘                   └────┘       └────┘
typ             └──┘        └┘  └┘    └────┘  └┘  └────┘  └┘
doc                                    └────┘        └────┘
320  by rw [countp_eq_length_filter, countp_eq_length_filter];
id          └─────────────────────┘  └─────────────────────┘
src     └──┘└─────────────────────┘└┘└─────────────────────┘
typ     └──┘└─────────────────────┘└┘└─────────────────────┘
doc     └──┘                       └┘                       
txt     └──┘                       └┘                       
par     └──┘                       └┘                       
pid       └┘                       └┘                       
st     └──────────────────────────┘└───────────────────────┘└─
321     exact perm_length (perm_filter _ s)
id            └─────────┘  └─────────┘   
src     └────┘└─────────┘ └─────────┘└─┘ └─
typ     └────┘└─────────┘ └─────────┘└─┘└─
doc     └────┘                       └─┘ └─
txt     └────┘                       └─┘ └─
par     └────┘                       └─┘ └─
pid                                 └─┘ 
st   ───────────────────────────────────────
322  
src  
typ  
doc  
txt  
par  
pid  
st   
323  theorem countp_le_of_subperm (p : α → Prop) [decidable_pred p]
id                                               └────────────┘ 
src                                               └────────────┘
typ                                              └────────────┘ 
324    {l₁ l₂ : list α} : l₁ <+~ l₂ → countp p l₁ ≤ countp p l₂
id              └──┘     └┘ └─┘ └┘  └────┘  └┘  └────┘  └┘
src             └──┘         └─┘      └────┘       └────┘
typ             └──┘     └┘ └─┘ └┘  └────┘  └┘  └────┘  └┘
doc                          └─┘      └────┘        └────┘
325  | ⟨l, p', s⟩ := perm_countp p p' ▸ countp_le_of_sublist s
id         └┘       └─────────┘      └──────────────────┘
src                  └─────────┘       └──────────────────┘
typ        └┘       └─────────┘      └──────────────────┘
326  
327  theorem perm_count [decidable_eq α] {l₁ l₂ : list α}
id                       └──────────┘            └──┘ 
src                      └──────────┘             └──┘
typ                      └──────────┘            └──┘ 
328    (p : l₁ ~ l₂) (a) : count a l₁ = count a l₂ :=
id          └┘  └┘        └───┘  └┘  └───┘  └┘
src                       └───┘       └───┘
typ         └┘  └┘        └───┘  └┘  └───┘  └┘
doc                       └───┘        └───┘
329  perm_countp _ p
id   └─────────┘   
src  └─────────┘
typ  └─────────┘   
330  
331  theorem count_le_of_subperm [decidable_eq α] {l₁ l₂ : list α}
id                                └──────────┘            └──┘ 
src                               └──────────┘             └──┘
typ                               └──────────┘            └──┘ 
332    (s : l₁ <+~ l₂) (a) : count a l₁ ≤ count a l₂ :=
id          └┘ └─┘ └┘        └───┘  └┘  └───┘  └┘
src            └─┘           └───┘       └───┘
typ         └┘ └─┘ └┘        └───┘  └┘  └───┘  └┘
doc            └─┘           └───┘        └───┘
333  countp_le_of_subperm _ s
id   └──────────────────┘   
src  └──────────────────┘
typ  └──────────────────┘   
334  
335  theorem foldl_eq_of_perm {f : β → α → β} {l₁ l₂ : list α} (rcomm : right_commutative f) (p : l₁ ~ l₂) :
id                                                  └──┘            └───────────────┘        └┘  └┘
src                                                    └──┘             └───────────────┘            
typ                                                 └──┘            └───────────────┘        └┘  └┘
doc                                                                                                  
336    ∀ b, foldl f b l₁ = foldl f b l₂ :=
id         └───┘   └┘  └───┘   └┘
src         └───┘         └───┘
typ        └───┘   └┘  └───┘   └┘
337  perm_induction_on p
id   └───────────────┘ 
src  └───────────────┘
typ  └───────────────┘ 
338    (λ b, rfl)
id          └─┘
src          └─┘
typ         └─┘
339    (λ x t₁ t₂ p r b, r (f b x))
id         └┘ └┘         
typ        └┘ └┘         
340    (λ x y t₁ t₂ p r b, by simp; rw rcomm; exact r (f (f b x) y))
id          └┘ └┘                 └───┘                 
src                           └──┘  └─┘       └────┘       └┘ 
typ         └┘ └┘        └──┘  └─┘└───┘  └────┘   └┘
doc                           └──┘  └─┘       └────┘       └┘ 
txt                           └──┘  └─┘       └────┘       └┘ 
par                           └──┘  └─┘       └────┘       └┘ 
pid                                                      └┘ 
st                           └────────┘└───┘└─────────────────────┘
341    (λ t₁ t₂ t₃ p₁ p₂ r₁ r₂ b, eq.trans (r₁ b) (r₂ b))
id        └┘ └┘ └┘ └┘ └┘ └┘ └┘   └──────┘  └┘    └┘ 
src                               └──────┘
typ       └┘ └┘ └┘ └┘ └┘ └┘ └┘   └──────┘  └┘    └┘ 
342  
343  theorem foldr_eq_of_perm {f : α → β → β} {l₁ l₂ : list α} (lcomm : left_commutative f) (p : l₁ ~ l₂) :
id                                                  └──┘            └──────────────┘        └┘  └┘
src                                                    └──┘             └──────────────┘            
typ                                                 └──┘            └──────────────┘        └┘  └┘
doc                                                                                                 
344    ∀ b, foldr f b l₁ = foldr f b l₂ :=
id         └───┘   └┘  └───┘   └┘
src         └───┘         └───┘
typ        └───┘   └┘  └───┘   └┘
345  perm_induction_on p
id   └───────────────┘ 
src  └───────────────┘
typ  └───────────────┘ 
346    (λ b, rfl)
id          └─┘
src          └─┘
typ         └─┘
347    (λ x t₁ t₂ p r b, by simp; rw [r b])
id         └┘ └┘                   
src                         └──┘  └──┘  
typ        └┘ └┘        └──┘  └──┘
doc                         └──┘  └──┘  
txt                         └──┘  └──┘  
par                         └──┘  └──┘  
pid                                 └┘  
st                         └─────────┘└─┘
348    (λ x y t₁ t₂ p r b, by simp; rw [lcomm, r b])
id          └┘ └┘                  └───┘   
src                           └──┘  └──┘     └┘  
typ         └┘ └┘        └──┘  └──┘└───┘└┘
doc                           └──┘  └──┘     └┘  
txt                           └──┘  └──┘     └┘  
par                           └──┘  └──┘     └┘  
pid                                   └┘     └┘  
st                           └─────────┘└───┘└───┘
349    (λ t₁ t₂ t₃ p₁ p₂ r₁ r₂ a, eq.trans (r₁ a) (r₂ a))
id        └┘ └┘ └┘ └┘ └┘ └┘ └┘   └──────┘  └┘    └┘ 
src                               └──────┘
typ       └┘ └┘ └┘ └┘ └┘ └┘ └┘   └──────┘  └┘    └┘ 
350  
351  lemma rec_heq_of_perm {β : list α → Sort*} {f : Πa l, β l → β (a::l)} {b : β []} {l l' : list α}
id                              └──┘                          └┘         └┘          └──┘ 
src                             └──┘                                 └┘           └┘          └──┘
typ                             └──┘                          └┘         └┘          └──┘ 
352    (hl : perm l l')
id           └──┘  └┘
src          └──┘
typ          └──┘  └┘
doc          └──┘
353    (f_congr : ∀{a l l' b b'}, perm l l' → b == b' → f a l b == f a l' b')
id                    └┘  └┘   └──┘  └┘    └┘ └┘       └┘   └┘ └┘
src                               └──┘          └┘              └┘
typ                   └┘  └┘   └──┘  └┘    └┘ └┘       └┘   └┘ └┘
doc                               └──┘
354    (f_swap : ∀{a a' l b}, f a (a'::l) (f a' l b) == f a' (a::l) (f a l b)) :
id                  └┘        └┘└┘    └┘    └┘  └┘  └┘      
src                                  └┘              └┘        └┘
typ                 └┘        └┘└┘    └┘    └┘  └┘  └┘      
355    @list.rec α β b f l == @list.rec α β b f l' :=
id      └──────┘      └┘  └──────┘     └┘
src     └──────┘           └┘  └──────┘
typ     └──────┘      └┘  └──────┘     └┘
356  begin
st   └─────
357    induction hl,
id               └┘
src    └────────┘
typ    └────────┘└┘
doc    └────────┘
txt    └────────┘
par    └────────┘
pid             
st   ─────────────┘└─
358    case list.perm.nil { refl },
src    └───────────────────┘└───┘
typ    └───────────────────┘└───┘
doc    └───────────────────┘└───┘
txt    └───────────────────┘└───┘
par    └───────────────────┘└───┘
pid        └────────────┘└──────┘
st   ─────────────────────┘└────┘└┘
359    case list.perm.skip : a l l' h ih { exact f_congr h ih },
id                                               └─────┘  └┘
src    └──────────────────────────────────┘└────┘          
typ    └──────────────────────────────────┘└────┘└─────┘└┘
doc    └──────────────────────────────────┘└────┘          
txt    └──────────────────────────────────┘└────┘          
par    └──────────────────────────────────┘└────┘          
pid        └─────────────┘└────────────┘└───────┘          └┘
st   ────────────────────────────────────┘└──────────────────┘└┘
360    case list.perm.swap : a a' l { exact f_swap },
id                                          └────┘
src    └─────────────────────────────┘└────┘      
typ    └─────────────────────────────┘└────┘└────┘
doc    └─────────────────────────────┘└────┘      
txt    └─────────────────────────────┘└────┘      
par    └─────────────────────────────┘└────┘      
pid        └─────────────┘└───────┘└───────┘      └┘
st   ───────────────────────────────┘└────────────┘└┘
361    case list.perm.trans : l₁ l₂ l₃ h₁ h₂ ih₁ ih₂ { exact heq.trans ih₁ ih₂ }
id                                                           └───────┘ └─┘ └─┘
src    └──────────────────────────────────────────────┘└────┘└───────┘      └┘
typ    └──────────────────────────────────────────────┘└────┘└───────┘└─┘└─┘└┘
doc    └──────────────────────────────────────────────┘└────┘               └┘
txt    └──────────────────────────────────────────────┘└────┘               └┘
par    └──────────────────────────────────────────────┘└────┘               └┘
pid        └──────────────┘└───────────────────────┘└───────┘               └┘
st   ────────────────────────────────────────────────┘└───────────────────────┘
362  end
st   └─┘
363  
364  section
365  variables {op : α → α → α} [is_associative α op] [is_commutative α op]
id                               └────────────┘        └────────────┘
src                              └────────────┘        └────────────┘
typ                              └────────────┘        └────────────┘
366  local notation a * b := op a b
367  local notation l <*> a := foldl op a l
id                             └───┘
src                            └───┘
typ                            └───┘
368  
369  lemma fold_op_eq_of_perm {l₁ l₂ : list α} {a : α} (h : l₁ ~ l₂) : l₁ <*> a = l₂ <*> a :=
id                                     └──┘               └┘  └┘    └┘ └─┘   └┘ └─┘ 
src                                    └──┘                              └─┘       └─┘
typ                                    └──┘               └┘  └┘    └┘ └─┘   └┘ └─┘ 
doc                                                            
370  foldl_eq_of_perm (right_comm _ (is_commutative.comm _) (is_associative.assoc _)) h _
id   └──────────────┘  └────────┘    └─────────────────┘     └──────────────────┘     
src  └──────────────┘  └────────┘    └─────────────────┘     └──────────────────┘
typ  └──────────────┘  └────────┘    └─────────────────┘     └──────────────────┘     
371  end
372  
373  section comm_monoid
374  open list
375  variable [comm_monoid α]
id             └─────────┘
src            └─────────┘
typ            └─────────┘
376  
377  @[to_additive]
doc    └─────────┘
378  lemma prod_eq_of_perm {l₁ l₂ : list α} (h : perm l₁ l₂) : prod l₁ = prod l₂ :=
id                                  └──┘        └──┘ └┘ └┘    └──┘ └┘  └──┘ └┘
src                                 └──┘         └──┘          └──┘     └──┘
typ                                 └──┘        └──┘ └┘ └┘    └──┘ └┘  └──┘ └┘
doc                                              └──┘          └──┘      └──┘
379  by induction h; simp [*, mul_left_comm]
id                           └───────────┘
src     └────────┘   └───────┘└───────────┘└─
typ     └────────┘  └───────┘└───────────┘└─
doc     └────────┘   └───────┘             └─
txt     └────────┘   └───────┘             └─
par     └────────┘   └───────┘             └─
pid                     └──┘             
st     └─────────────────────────────────────
380  
src  
typ  
doc  
txt  
par  
pid  
st   
381  @[to_additive]
doc    └─────────┘
382  lemma prod_reverse (l : list α) : prod l.reverse = prod l :=
id                           └──┘     └──┘ └──────┘  └──┘ 
src                          └──┘      └──┘  └──────┘  └──┘
typ                          └──┘     └──┘ └──────┘  └──┘ 
doc                                    └──┘             └──┘
383  prod_eq_of_perm $ reverse_perm l
id   └─────────────┘   └──────────┘ 
src  └─────────────┘   └──────────┘
typ  └─────────────┘   └──────────┘ 
384  
385  end comm_monoid
386  
387  theorem perm_inv_core {a : α} {l₁ l₂ r₁ r₂ : list α} : l₁++a::r₁ ~ l₂++a::r₂ → l₁++r₁ ~ l₂++r₂ :=
id                                               └──┘     └┘└┘└┘└┘  └┘└┘└┘└┘   └┘└┘└┘  └┘└┘└┘
src                                               └──┘        └┘ └┘      └┘ └┘       └┘      └┘
typ                                              └──┘     └┘└┘└┘└┘  └┘└┘└┘└┘   └┘└┘└┘  └┘└┘└┘
doc                                                                                       
388  begin
st   └─────
389    generalize e₁ : l₁++a::r₁ = s₁, generalize e₂ : l₂++a::r₂ = s₂,
id                     └┘└┘  └┘                       └┘    └┘
src    └──────────────┘  └┘          └──────────────┘          
typ    └──────────────┘└┘└┘  └┘     └──────────────┘└┘    └┘ 
doc    └──────────────┘              └──────────────┘          
txt    └──────────────┘              └──────────────┘          
par    └──────────────┘              └──────────────┘          
pid              └─┘└┘                        └─┘└┘          
st   ───────────────────────────────┘└──────────────────────────────┘└─
390    intro p, revert l₁ l₂ r₁ r₂ e₁ e₂,
src    └─────┘  └──────────────────────┘
typ    └─────┘  └──────────────────────┘
doc    └─────┘  └──────────────────────┘
txt    └─────┘  └──────────────────────┘
par    └─────┘  └──────────────────────┘
pid         └┘        └────────────────┘
st   ────────┘└────────────────────────┘└─
391    refine perm_induction_on p _ (λ x t₁ t₂ p IH, _) (λ x y t₁ t₂ p IH, _) (λ t₁ t₂ t₃ p₁ p₂ IH₁ IH₂, _);
id            └───────────────┘ 
src    └─────┘└───────────────┘ └─┘  └────────────────┘  └──────────────────┘  └─────────────────────────┘
typ    └─────┘└───────────────┘└─┘  └────────────────┘  └──────────────────┘  └─────────────────────────┘
doc    └─────┘                  └─┘  └────────────────┘  └──────────────────┘  └─────────────────────────┘
txt    └─────┘                  └─┘  └────────────────┘  └──────────────────┘  └─────────────────────────┘
par    └─────┘                  └─┘  └────────────────┘  └──────────────────┘  └─────────────────────────┘
pid                            └─┘  └────────────────┘  └──────────────────┘  └─────────────────────────┘
st   ────────────────────────────────────────────────────────────────────────────────────────────────────────
392      intros l₁ l₂ r₁ r₂ e₁ e₂,
src      └──────────────────────┘
typ      └──────────────────────┘
doc      └──────────────────────┘
txt      └──────────────────────┘
par      └──────────────────────┘
pid            └────────────────┘
st   ───────────────────────────┘└─
393    { apply (not_mem_nil a).elim, rw ← e₁, simp },
id              └─────────┘              └┘
src      └────┘ └─────────┘ └────┘  └───┘    └───┘
typ      └────┘ └─────────┘└────┘  └───┘└┘  └───┘
doc      └────┘             └────┘  └───┘    └───┘
txt      └────┘             └────┘  └───┘    └───┘
par      └────┘             └────┘  └───┘    └───┘
pid                        └───┘    └─┘        
st   ───┘└────────────────────────┘└───────┘└─────┘└┘
394    { cases l₁ with y l₁; cases l₂ with z l₂;
id             └┘                  └┘
src      └────┘  └────────┘  └────┘  └────────┘
typ      └────┘└┘└────────┘  └────┘└┘└────────┘
doc      └────┘  └────────┘  └────┘  └────────┘
txt      └────┘  └────────┘  └────┘  └────────┘
par      └────┘  └────────┘  └────┘  └────────┘
pid             └────────┘         └────────┘
st   ───┘└───────────────────────────────────────
395        dsimp at e₁ e₂; injections; subst x,
id                                           
src        └────────────┘  └────────┘  └────┘
typ        └────────────┘  └────────┘  └────┘
doc        └────────────┘  └────────┘  └────┘
txt        └────────────┘  └────────┘  └────┘
par        └────────────┘  └────────┘  └────┘
pid             └──────┘                   
st   ────────────────────────────────────────┘└─
396      { substs t₁ t₂,     exact p },
id                                 
src        └──────────┘      └────┘ 
typ        └──────────┘      └────┘
doc        └──────────┘      └────┘ 
txt        └──────────┘      └────┘ 
par        └──────────┘      └────┘ 
pid              └────┘            
st   ─────┘└──────────┘└────────────┘└┘
397      { substs z t₁ t₂,   exact p.trans perm_middle },
id                                 └─────┘ └─────────┘
src        └────────────┘    └────┘└─────┘└─────────┘
typ        └────────────┘    └────┘└─────┘└─────────┘
doc        └────────────┘    └────┘                  
txt        └────────────┘    └────┘                  
par        └────────────┘    └────┘                  
pid              └──────┘                           
st   ─────┘└────────────┘└────────────────────────────┘└┘
398      { substs y t₁ t₂,   exact perm_middle.symm.trans p },
id                                 └────────────────────┘ 
src        └────────────┘    └────┘└────────────────────┘ 
typ        └────────────┘    └────┘└────────────────────┘
doc        └────────────┘    └────┘                       
txt        └────────────┘    └────┘                       
par        └────────────┘    └────┘                       
pid              └──────┘                                
st   ─────┘└────────────┘└─────────────────────────────────┘└┘
399      { substs z t₁ t₂,   exact skip y (IH rfl rfl) } },
id                                 └──┘   └┘     └─┘
src        └────────────┘    └────┘└──┘       └─┘└┘
typ        └────────────┘    └────┘└──┘ └┘   └─┘└┘
doc        └────────────┘    └────┘              └┘
txt        └────────────┘    └────┘              └┘
par        └────────────┘    └────┘              └┘
pid              └──────┘                       
st   ───────────────────┘└────────────────────────────┘└──┘
400    { rcases l₁ with _|⟨y, _|⟨z, l₁⟩⟩; rcases l₂ with _|⟨u, _|⟨v, l₂⟩⟩;
id              └┘                               └┘
src      └─────┘  └────────────────────┘  └─────┘  └────────────────────┘
typ      └─────┘└┘└────────────────────┘  └─────┘└┘└────────────────────┘
doc      └─────┘  └────────────────────┘  └─────┘  └────────────────────┘
txt      └─────┘  └────────────────────┘  └─────┘  └────────────────────┘
par      └─────┘  └────────────────────┘  └─────┘  └────────────────────┘
pid              └────────────────────┘          └────────────────────┘
st   ───┘└─────────────────────────────────────────────────────────────────
401        dsimp at e₁ e₂; injections; substs x y,
src        └────────────┘  └────────┘  └────────┘
typ        └────────────┘  └────────┘  └────────┘
doc        └────────────┘  └────────┘  └────────┘
txt        └────────────┘  └────────┘  └────────┘
par        └────────────┘  └────────┘  └────────┘
pid             └──────┘                    └──┘
st   ───────────────────────────────────────────┘└─
402      { substs r₁ r₂,     exact skip a p },
id                                 └──┘  
src        └──────────┘      └────┘└──┘  
typ        └──────────┘      └────┘└──┘
doc        └──────────┘      └────┘      
txt        └──────────┘      └────┘      
par        └──────────┘      └────┘      
pid              └────┘                 
st   ─────┘└──────────┘└───────────────────┘└┘
403      { substs r₁ r₂,     exact skip u p },
id                                 └──┘  
src        └──────────┘      └────┘└──┘  
typ        └──────────┘      └────┘└──┘
doc        └──────────┘      └────┘      
txt        └──────────┘      └────┘      
par        └──────────┘      └────┘      
pid              └────┘                 
st   ─────┘└──────────┘└───────────────────┘└┘
404      { substs r₁ v t₂,   exact skip u (p.trans perm_middle) },
id                                 └──┘   └─────┘ └─────────┘
src        └────────────┘    └────┘└──┘  └─────┘└─────────┘└┘
typ        └────────────┘    └────┘└──┘ └─────┘└─────────┘└┘
doc        └────────────┘    └────┘                        └┘
txt        └────────────┘    └────┘                        └┘
par        └────────────┘    └────┘                        └┘
pid              └──────┘                                 
st   ─────┘└────────────┘└─────────────────────────────────────┘└┘
405      { substs r₁ r₂,     exact skip y p },
id                                 └──┘  
src        └──────────┘      └────┘└──┘  
typ        └──────────┘      └────┘└──┘
doc        └──────────┘      └────┘      
txt        └──────────┘      └────┘      
par        └──────────┘      └────┘      
pid              └────┘                 
st   ─────┘└──────────┘└───────────────────┘└┘
406      { substs r₁ r₂ y u, exact skip a p },
id                                 └──┘  
src        └──────────────┘  └────┘└──┘  
typ        └──────────────┘  └────┘└──┘
doc        └──────────────┘  └────┘      
txt        └──────────────┘  └────┘      
par        └──────────────┘  └────┘      
pid              └────────┘             
st   ─────┘└──────────────┘└───────────────┘└┘
407      { substs r₁ u v t₂, exact (skip y $ p.trans perm_middle).trans (swap _ _ _) },
id                                  └──┘    └─────┘ └─────────┘         └──┘
src        └──────────────┘  └────┘ └──┘  └─────┘└─────────┘└──────┘ └──┘└──────┘
typ        └──────────────┘  └────┘ └──┘ └─────┘└─────────┘└──────┘ └──┘└──────┘
doc        └──────────────┘  └────┘                         └──────┘     └──────┘
txt        └──────────────┘  └────┘                         └──────┘     └──────┘
par        └──────────────┘  └────┘                         └──────┘     └──────┘
pid              └────────┘                                └──────┘     └─────┘
st   ─────┘└──────────────┘└────────────────────────────────────────────────────────┘└┘
408      { substs r₂ z t₁,   exact skip y (perm_middle.symm.trans p) },
id                                 └──┘   └────────────────────┘ 
src        └────────────┘    └────┘└──┘  └────────────────────┘ └┘
typ        └────────────┘    └────┘└──┘ └────────────────────┘└┘
doc        └────────────┘    └────┘                             └┘
txt        └────────────┘    └────┘                             └┘
par        └────────────┘    └────┘                             └┘
pid              └──────┘                                      
st   ─────┘└────────────┘└──────────────────────────────────────────┘└┘
409      { substs r₂ y z t₁, exact (swap _ _ _).trans (skip u $ perm_middle.symm.trans p) },
id                                  └──┘               └──┘    └────────────────────┘ 
src        └──────────────┘  └────┘ └──┘└────────────┘ └──┘  └────────────────────┘ └┘
typ        └──────────────┘  └────┘ └──┘└────────────┘ └──┘ └────────────────────┘└┘
doc        └──────────────┘  └────┘     └────────────┘                              └┘
txt        └──────────────┘  └────┘     └────────────┘                              └┘
par        └──────────────┘  └────┘     └────────────┘                              └┘
pid              └────────┘            └────────────┘                              
st   ─────┘└──────────────┘└─────────────────────────────────────────────────────────────┘└┘
410      { substs u v t₁ t₂, exact (IH rfl rfl).swap' _ _ } },
id                                  └┘     └─┘
src        └──────────────┘  └────┘      └─┘└──────────┘
typ        └──────────────┘  └────┘ └┘   └─┘└──────────┘
doc        └──────────────┘  └────┘         └──────────┘
txt        └──────────────┘  └────┘         └──────────┘
par        └──────────────┘  └────┘         └──────────┘
pid              └────────┘                └─────────┘
st   ─────────────────────┘└─────────────────────────────┘└──┘
411    { substs t₁ t₃,
src      └──────────┘
typ      └──────────┘
doc      └──────────┘
txt      └──────────┘
par      └──────────┘
pid            └────┘
st   ───────────────┘└─
412      have : a ∈ t₂ := perm_subset p₁ (by simp),
id                └┘    └─────────┘ └┘
src      └─────┘   └──┘└─────────┘     └──┘
typ      └─────┘└┘└──┘└─────────┘└┘   └──┘
doc      └─────┘    └──┘                └──┘
txt      └─────┘    └──┘                └──┘
par      └─────┘    └──┘                └──┘
pid      └───┘└┘    └──┘                └────┘
st   ──────────────────────────────────────┘└───┘└─
413      rcases mem_split this with ⟨l₂, r₂, e₂⟩,
id              └───────┘ └──┘
src      └─────┘└───────┘    └────────────────┘
typ      └─────┘└───────┘└──┘└────────────────┘
doc      └─────┘             └────────────────┘
txt      └─────┘             └────────────────┘
par      └─────┘             └────────────────┘
pid                         └────────────────┘
st   ──────────────────────────────────────────┘└─
414      subst t₂, exact (IH₁ rfl rfl).trans (IH₂ rfl rfl) }
id             └┘         └─┘                 └─┘     └─┘
src      └────┘    └────┘          └──────┘       └─┘└┘
typ      └────┘└┘  └────┘ └─┘      └──────┘ └─┘   └─┘└┘
doc      └────┘    └────┘          └──────┘          └┘
txt      └────┘    └────┘          └──────┘          └┘
par      └────┘    └────┘          └──────┘          └┘
pid                              └──────┘          
st   ───────────┘└────────────────────────────────────────┘└─
415  end
st   ──┘
416  
417  theorem perm_cons_inv {a : α} {l₁ l₂ : list α} : a::l₁ ~ a::l₂ → l₁ ~ l₂ :=
id                                         └──┘     └┘└┘  └┘└┘   └┘  └┘
src                                         └──┘       └┘     └┘        
typ                                        └──┘     └┘└┘  └┘└┘   └┘  └┘
doc                                                                     
418  @perm_inv_core _ _ [] [] _ _
id    └───────────┘     └┘ └┘
src   └───────────┘     └┘ └┘
typ   └───────────┘     └┘ └┘
419  
420  theorem perm_cons (a : α) {l₁ l₂ : list α} : a::l₁ ~ a::l₂ ↔ l₁ ~ l₂ :=
id                                     └──┘     └┘└┘  └┘└┘  └┘  └┘
src                                     └──┘       └┘     └┘       
typ                                    └──┘     └┘└┘  └┘└┘  └┘  └┘
doc                                                                 
421  ⟨perm_cons_inv, skip a⟩
id    └───────────┘  └──┘ 
src   └───────────┘  └──┘
typ   └───────────┘  └──┘ 
422  
423  theorem perm_app_left_iff {l₁ l₂ : list α} : ∀ l, l++l₁ ~ l++l₂ ↔ l₁ ~ l₂
id                                      └──┘         └┘└┘  └┘└┘  └┘  └┘
src                                     └──┘            └┘     └┘       
typ                                     └──┘         └┘└┘  └┘└┘  └┘  └┘
doc                                                                      
424  | []     := iff.rfl
id     └┘        └─────┘
src    └┘        └─────┘
typ    └┘        └─────┘
425  | (a::l) := (perm_cons a).trans (perm_app_left_iff l)
id      └┘      └───────┘   └───┘   └───────────────┘
src      └┘       └───────┘   └───┘
typ     └┘      └───────┘   └───┘   └───────────────┘
426  
427  theorem perm_app_right_iff {l₁ l₂ : list α} (l) : l₁++l ~ l₂++l ↔ l₁ ~ l₂ :=
id                                       └──┘         └┘└┘  └┘└┘  └┘  └┘
src                                      └──┘            └┘     └┘      
typ                                      └──┘         └┘└┘  └┘└┘  └┘  └┘
doc                                                                      
428  ⟨λ p, (perm_app_left_iff _).1 $ trans perm_app_comm $ trans p perm_app_comm,
id         └───────────────┘       └───┘ └───────────┘   └───┘  └───────────┘
src         └───────────────┘       └───┘ └───────────┘   └───┘   └───────────┘
typ        └───────────────┘       └───┘ └───────────┘   └───┘  └───────────┘
429   perm_app_left _⟩
id    └───────────┘
src   └───────────┘
typ   └───────────┘
430  
431  theorem perm_option_to_list {o₁ o₂ : option α} : o₁.to_list ~ o₂.to_list ↔ o₁ = o₂ :=
id                                        └────┘     └┘└──────┘  └┘└──────┘  └┘  └┘
src                                       └────┘        └──────┘    └──────┘     
typ                                       └────┘     └┘└──────┘  └┘└──────┘  └┘  └┘
doc                                                              
432  begin
st   └─────
433    refine ⟨λ p, _, λ e, e ▸ perm.refl _⟩,
id                             └───────┘
src    └─────┘  └─────┘ └──┘ └───────┘└─┘
typ    └─────┘  └─────┘ └──┘ └───────┘└─┘
doc    └─────┘  └─────┘ └──┘           └─┘
txt    └─────┘  └─────┘ └──┘           └─┘
par    └─────┘  └─────┘ └──┘           └─┘
pid            └─────┘ └──┘           └─┘
st   ──────────────────────────────────────┘└─
434    cases o₁ with a; cases o₂ with b, {refl},
id           └┘               └┘
src    └────┘  └─────┘  └────┘  └─────┘   └──┘
typ    └────┘└┘└─────┘  └────┘└┘└─────┘   └──┘
doc    └────┘  └─────┘  └────┘  └─────┘   └──┘
txt    └────┘  └─────┘  └────┘  └─────┘   └──┘
par    └────┘  └─────┘  └────┘  └─────┘   └──┘
pid           └─────┘         └─────┘
st   ─────────────────────────────────┘└─────┘└┘
435    { cases (perm_length p) },
id              └─────────┘ 
src      └────┘ └─────────┘ └┘
typ      └────┘ └─────────┘└┘
doc      └────┘             └┘
txt      └────┘             └┘
par      └────┘             └┘
pid                        
st   ───┘└────────────────────┘└┘
436    { cases (perm_length p) },
id              └─────────┘ 
src      └────┘ └─────────┘ └┘
typ      └────┘ └─────────┘└┘
doc      └────┘             └┘
txt      └────┘             └┘
par      └────┘             └┘
pid                        
st   ───┘└────────────────────┘└┘
437    { exact option.mem_to_list.1 ((mem_of_perm p).2 $ by simp) }
id             └────────────────┘     └─────────┘ 
src      └────┘└────────────────┘└─┘  └─────────┘ └──┘   └──┘└┘
typ      └────┘└────────────────┘└─┘  └─────────┘└──┘   └──┘└┘
doc      └────┘                  └─┘              └──┘   └──┘└┘
txt      └────┘                  └─┘              └──┘   └──┘└┘
par      └────┘                  └─┘              └──┘   └──┘└┘
pid                             └─┘              └──┘   └────┘
st   ─────────────────────────────────────────────────────┘└───┘└┘└─
438  end
st   ──┘
439  
440  theorem subperm_cons (a : α) {l₁ l₂ : list α} : a::l₁ <+~ a::l₂ ↔ l₁ <+~ l₂ :=
id                                        └──┘     └┘└┘ └─┘ └┘└┘  └┘ └─┘ └┘
src                                        └──┘       └┘   └─┘  └┘       └─┘
typ                                       └──┘     └┘└┘ └─┘ └┘└┘  └┘ └─┘ └┘
doc                                                        └─┘            └─┘
441  ⟨λ ⟨l, p, s⟩, begin
id      
typ     
st                 └─────
442    cases s with _ _ _ s' u _ _ s',
id           
src    └────┘ └─────────────────────┘
typ    └────┘└─────────────────────┘
doc    └────┘ └─────────────────────┘
txt    └────┘ └─────────────────────┘
par    └────┘ └─────────────────────┘
pid          └─────────────────────┘
st   ───────────────────────────────┘└─
443    { exact (p.subperm_left.2 $ subperm_of_sublist $ sublist_cons _ _).trans
id              └────────────┘                          └──────────┘
src      └────┘ └────────────┘└─┘                    └──────────┘└───────────
typ      └────┘ └────────────┘└─┘                    └──────────┘└───────────
doc      └────┘               └─┘                                └───────────
txt      └────┘               └─┘                                └───────────
par      └────┘               └─┘                                └───────────
pid                          └─┘                                └───────────
st   ───┘└──────────────────────────────────────────────────────────────────────
444       (subperm_of_sublist s') },
id         └────────────────┘ └┘
src  ────┘ └────────────────┘  └┘
typ  ────┘ └────────────────┘└┘└┘
doc  ────┘                     └┘
txt  ────┘                     └┘
par  ────┘                     └┘
pid  ────┘                     
st   ────────────────────────────┘└┘
445    { exact ⟨u, perm_cons_inv p, s'⟩ }
id                └───────────┘   └┘
src      └────┘  └┘└───────────┘ └┘  └┘
typ      └────┘ └┘└───────────┘└┘└┘└┘
doc      └────┘  └┘              └┘  └┘
txt      └────┘  └┘              └┘  └┘
par      └────┘  └┘              └┘  └┘
pid             └┘              └┘  
st   ──────────────────────────────────┘└─
446  end, λ ⟨l, p, s⟩, ⟨a::l, skip a p, s.cons2 _ _ _⟩⟩
id                  └┘   └──┘      └────┘
src                      └┘   └──┘       └────┘
typ                 └┘   └──┘      └────┘
st   ──┘
447  
448  theorem cons_subperm_of_mem {a : α} {l₁ l₂ : list α} (d₁ : nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
id                                               └──┘         └───┘ └┘          └┘          └┘
src                                               └──┘          └───┘                          
typ                                              └──┘         └───┘ └┘          └┘          └┘
doc                                                             └───┘
449   (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ :=
id         └┘ └─┘ └┘     └┘ └┘ └─┘ └┘
src           └─┘         └┘    └─┘
typ        └┘ └─┘ └┘     └┘ └┘ └─┘ └┘
doc           └─┘               └─┘
450  begin
st   └─────
451    rcases s with ⟨l, p, s⟩,
id            
src    └─────┘ └─────────────┘
typ    └─────┘└─────────────┘
doc    └─────┘ └─────────────┘
txt    └─────┘ └─────────────┘
par    └─────┘ └─────────────┘
pid           └─────────────┘
st   ────────────────────────┘└─
452    induction s generalizing l₁,
id               
src    └────────┘ └──────────────┘
typ    └────────┘└──────────────┘
doc    └────────┘ └──────────────┘
txt    └────────┘ └──────────────┘
par    └────────┘ └──────────────┘
pid              └─────────────┘
st   ────────────────────────────┘└─
453    case list.sublist.slnil { cases h₂ },
id                                     └┘
src    └────────────────────────┘└────┘  
typ    └────────────────────────┘└────┘└┘
doc    └────────────────────────┘└────┘  
txt    └────────────────────────┘└────┘  
par    └────────────────────────┘└────┘  
pid        └─────────────────┘└──────┘  └┘
st   ──────────────────────────┘└────────┘└┘
454    case list.sublist.cons : r₁ r₂ b s' ih {
src    └────────────────────────────────────────
typ    └────────────────────────────────────────
doc    └────────────────────────────────────────
txt    └────────────────────────────────────────
par    └────────────────────────────────────────
pid        └────────────────┘└──────────────┘└──
st   ─────────────────────────────────────────┘
455      simp at h₂,
src  ───┘└────────┘└─
typ  ───┘└────────┘└─
doc  ───┘└────────┘└─
txt  ───┘└────────┘└─
par  ───┘└────────┘└─
pid  ────────────────
st   ─────────────┘└─
456      cases h₂ with e m,
id             └┘
src  ───┘└────┘  └───────┘└─
typ  ───┘└────┘└┘└───────┘└─
doc  ───┘└────┘  └───────┘└─
txt  ───┘└────┘  └───────┘└─
par  ───┘└────┘  └───────┘└─
pid  ─────────┘  └──────────
st   ────────────────────┘└─
457      { subst b, exact ⟨a::r₁, skip a p, s'.cons2 _ _ _⟩ },
id                           └┘  └──┘    └──────┘
src  ─────┘└────┘ └┘└────┘      └┘└──┘  └┘└──────┘└──────┘└──
typ  ─────┘└────┘└┘└────┘    └┘└┘└──┘└┘└──────┘└──────┘└──
doc  ─────┘└────┘ └┘└────┘      └┘      └┘        └──────┘└──
txt  ─────┘└────┘ └┘└────┘      └┘      └┘        └──────┘└──
par  ─────┘└────┘ └┘└────┘      └┘      └┘        └──────┘└──
pid  ───────────┘ └──────┘      └┘      └┘        └──────────
st   ────┘└──────┘└────────────────────────────────────────┘└─
458      { rcases ih m d₁ h₁ p with ⟨t, p', s'⟩, exact ⟨t, p', s'.cons _ _ _⟩ } },
id                └┘  └┘ └┘                             └┘  └─────┘
src  ─────┘└─────┘        └───────────────┘└┘└────┘  └┘  └┘└─────┘└──────┘└─┘
typ  ─────┘└─────┘└┘└┘└┘└───────────────┘└┘└────┘ └┘└┘└┘└─────┘└──────┘└─┘
doc  ─────┘└─────┘        └───────────────┘└┘└────┘  └┘  └┘       └──────┘└─┘
txt  ─────┘└─────┘        └───────────────┘└┘└────┘  └┘  └┘       └──────┘└─┘
par  ─────┘└─────┘        └───────────────┘└┘└────┘  └┘  └┘       └──────┘└─┘
pid  ────────────┘        └───────────────────────┘  └┘  └┘       └─────────┘
st   ─────────────────────────────────────────┘└─────────────────────────────┘└──┘
459    case list.sublist.cons2 : r₁ r₂ b s' ih {
src    └─────────────────────────────────────────
typ    └─────────────────────────────────────────
doc    └─────────────────────────────────────────
txt    └─────────────────────────────────────────
par    └─────────────────────────────────────────
pid        └─────────────────┘└──────────────┘└──
st   ──────────────────────────────────────────┘
460      have bm : b ∈ l₁ := (perm_subset p $ mem_cons_self _ _),
id                   └┘     └─────────┘    └───────────┘
src  ───┘└────────┘   └──┘ └─────────┘  └───────────┘└───┘└─
typ  ───┘└────────┘└┘└──┘ └─────────┘ └───────────┘└───┘└─
doc  ───┘└────────┘    └──┘                           └───┘└─
txt  ───┘└────────┘    └──┘                           └───┘└─
par  ───┘└────────┘    └──┘                           └───┘└─
pid  ─────────────┘    └──┘                           └──────
st   ──────────────────────────────────────────────────────────┘└─
461      have am : a ∈ r₂ := h₂.resolve_left (λ e, h₁ $ e.symm ▸ bm),
id                    └┘    └─────────────┘       └┘    └───┘  └┘
src  ───┘└────────┘    └──┘└─────────────┘  └──┘    └───┘  └─
typ  ───┘└────────┘ └┘└──┘└─────────────┘  └──┘└┘  └───┘└┘└─
doc  ───┘└────────┘    └──┘                 └──┘            └─
txt  ───┘└────────┘    └──┘                 └──┘            └─
par  ───┘└────────┘    └──┘                 └──┘            └─
pid  ─────────────┘    └──┘                 └──┘            └──
st   ──────────────────────────────────────────────────────────────┘└─
462      rcases mem_split bm with ⟨t₁, t₂, rfl⟩,
id              └───────┘ └┘
src  ───┘└─────┘└───────┘  └─────────────────┘└─
typ  ───┘└─────┘└───────┘└┘└─────────────────┘└─
doc  ───┘└─────┘           └─────────────────┘└─
txt  ───┘└─────┘           └─────────────────┘└─
par  ───┘└─────┘           └─────────────────┘└─
pid  ──────────┘           └────────────────────
st   ─────────────────────────────────────────┘└─
463      have st : t₁ ++ t₂ <+ t₁ ++ b :: t₂ := by simp,
id                    └┘    └┘ └┘        └┘
src  ───┘└────────┘  └┘  └┘         └──┘  └──┘└─
typ  ───┘└────────┘  └┘  └┘└┘    └┘└──┘  └──┘└─
doc  ───┘└────────┘                 └──┘  └──┘└─
txt  ───┘└────────┘                 └──┘  └──┘└─
par  ───┘└────────┘                 └──┘  └──┘└─
pid  ─────────────┘                 └──┘  └──────
st   ────────────────────────────────────────────┘└───┘└─
464      rcases ih am (nodup_of_sublist st d₁)
id              └┘ └┘  └──────────────┘    └┘
src  ───┘└─────┘     └──────────────┘    └─
typ  ───┘└─────┘└┘└┘ └──────────────┘  └┘└─
doc  ───┘└─────┘                         └─
txt  ───┘└─────┘                         └─
par  ───┘└─────┘                         └─
pid  ──────────┘                         └─
st   ──────────────────────────────────────────
465        (mt (λ x, subset_of_sublist st x) h₁)
id          └┘       └───────────────┘ └┘    └┘
src  ─────┘ └┘  └──┘└───────────────┘   └┘  └─
typ  ─────┘ └┘  └──┘└───────────────┘└┘ └┘└┘└─
doc  ─────┘     └──┘                    └┘  └─
txt  ─────┘     └──┘                    └┘  └─
par  ─────┘     └──┘                    └┘  └─
pid  ─────┘     └──┘                    └┘  └─
st   ────────────────────────────────────────────
466        (perm_cons_inv $ p.trans perm_middle) with ⟨t, p', s'⟩,
id          └───────────┘   └─────┘ └─────────┘
src  ─────┘ └───────────┘ └─────┘└─────────┘└────────────────┘└─
typ  ─────┘ └───────────┘ └─────┘└─────────┘└────────────────┘└─
doc  ─────┘                                 └────────────────┘└─
txt  ─────┘                                 └────────────────┘└─
par  ─────┘                                 └────────────────┘└─
pid  ─────┘                                 └───────────────────
st   ───────────────────────────────────────────────────────────┘└─
467      exact ⟨b::t, (skip b p').trans $ (swap _ _ _).trans (skip a perm_middle.symm), s'.cons2 _ _ _⟩ }
id                          └┘           └──┘               └──┘  └──────────────┘   └──────┘
src  ───┘└────┘     └┘        └──────┘  └──┘└────────────┘ └──┘ └──────────────┘└─┘└──────┘└──────┘└┘
typ  ───┘└────┘    └┘     └┘└──────┘  └──┘└────────────┘ └──┘└──────────────┘└─┘└──────┘└──────┘└┘
doc  ───┘└────┘     └┘        └──────┘      └────────────┘                      └─┘        └──────┘└┘
txt  ───┘└────┘     └┘        └──────┘      └────────────┘                      └─┘        └──────┘└┘
par  ───┘└────┘     └┘        └──────┘      └────────────┘                      └─┘        └──────┘└┘
pid  ─────────┘     └┘        └──────┘      └────────────┘                      └─┘        └───────┘
st   ──────────────────────────────────────────────────────────────────────────────────────────────────┘
468  end
st   └─┘
469  
470  theorem subperm_app_left {l₁ l₂ : list α} : ∀ l, l++l₁ <+~ l++l₂ ↔ l₁ <+~ l₂
id                                     └──┘         └┘└┘ └─┘ └┘└┘  └┘ └─┘ └┘
src                                    └──┘            └┘   └─┘  └┘       └─┘
typ                                    └──┘         └┘└┘ └─┘ └┘└┘  └┘ └─┘ └┘
doc                                                         └─┘            └─┘
471  | []     := iff.rfl
id     └┘        └─────┘
src    └┘        └─────┘
typ    └┘        └─────┘
472  | (a::l) := (subperm_cons a).trans (subperm_app_left l)
id      └┘      └──────────┘   └───┘   └──────────────┘
src      └┘       └──────────┘   └───┘
typ     └┘      └──────────┘   └───┘   └──────────────┘
473  
474  theorem subperm_app_right {l₁ l₂ : list α} (l) : l₁++l <+~ l₂++l ↔ l₁ <+~ l₂ :=
id                                      └──┘         └┘└┘ └─┘ └┘└┘  └┘ └─┘ └┘
src                                     └──┘            └┘  └─┘   └┘      └─┘
typ                                     └──┘         └┘└┘ └─┘ └┘└┘  └┘ └─┘ └┘
doc                                                         └─┘            └─┘
475  (perm_app_comm.subperm_left.trans perm_app_comm.subperm_right).trans (subperm_app_left l)
id    └───────────┘└───────────┘└────┘ └───────────┘└────────────┘ └───┘   └──────────────┘ 
src   └───────────┘└───────────┘└────┘ └───────────┘└────────────┘ └───┘   └──────────────┘
typ   └───────────┘└───────────┘└────┘ └───────────┘└────────────┘ └───┘   └──────────────┘ 
476  
477  theorem subperm.exists_of_length_lt {l₁ l₂ : list α} :
id                                                └──┘ 
src                                               └──┘
typ                                               └──┘ 
478    l₁ <+~ l₂ → length l₁ < length l₂ → ∃ a, a :: l₁ <+~ l₂
id     └┘ └─┘ └┘  └────┘ └┘  └────┘ └┘      └┘ └┘ └─┘ └┘
src       └─┘      └────┘     └────┘           └┘    └─┘
typ    └┘ └─┘ └┘  └────┘ └┘  └────┘ └┘      └┘ └┘ └─┘ └┘
doc       └─┘                                           └─┘
479  | ⟨l, p, s⟩ h :=
id             
typ            
480    suffices length l < length l₂ → ∃ (a : α), a :: l <+~ l₂, from
id              └────┘    └────┘ └┘            └┘   └─┘ └┘
src             └────┘    └────┘                 └┘   └─┘
typ             └────┘    └────┘ └┘            └┘   └─┘ └┘
doc                                                      └─┘
481    (this $ perm_length p.symm ▸ h).imp (λ a, (skip a p).subperm_right.1),
id      └──┘   └─────────┘  └───┘    └─┘        └──┘    └───────────┘ 
src            └─────────┘  └───┘    └─┘         └──┘     └───────────┘ 
typ     └──┘   └─────────┘  └───┘    └─┘        └──┘    └───────────┘ 
482    begin
st     └─────
483      clear subperm.exists_of_length_lt p h l₁, rename l₂ u,
src      └──────────────────────────────────────┘  └─────────┘
typ      └──────────────────────────────────────┘  └─────────┘
doc      └──────────────────────────────────────┘  └─────────┘
txt      └──────────────────────────────────────┘  └─────────┘
par      └──────────────────────────────────────┘  └─────────┘
pid           └─────────────────────────────────┘        └─┘└┘
st   ───────────────────────────────────────────┘└───────────┘└─
484      induction s with l₁ l₂ a s IH _ _ b s IH; intro h,
id                 
src      └────────┘ └───────────────────────────┘  └─────┘
typ      └────────┘└───────────────────────────┘  └─────┘
doc      └────────┘ └───────────────────────────┘  └─────┘
txt      └────────┘ └───────────────────────────┘  └─────┘
par      └────────┘ └───────────────────────────┘  └─────┘
pid                └──────────────────────────┘       └┘
st   ────────────────────────────────────────────────────┘└─
485      { cases h },
id               
src        └────┘ 
typ        └────┘
doc        └────┘ 
txt        └────┘ 
par        └────┘ 
pid              
st   ─────┘└──────┘└┘
486      { cases lt_or_eq_of_le (nat.le_of_lt_succ h : length l₁ ≤ length l₂) with h h,
id               └────────────┘  └───────────────┘           └┘  └────┘ └┘
src        └────┘└────────────┘ └───────────────┘ └─┘        └────┘  └────────┘
typ        └────┘└────────────┘ └───────────────┘└─┘      └┘└────┘└┘└────────┘
doc        └────┘                                 └─┘                 └────────┘
txt        └────┘                                 └─┘                 └────────┘
par        └────┘                                 └─┘                 └────────┘
pid                                              └─┘                 └───────┘
st   ─────┘└─────────────────────────────────────────────────────────────────────────┘└─
487        { exact (IH h).imp (λ a s, s.trans (subperm_of_sublist $ sublist_cons _ _)) },
id                  └┘                └────┘  └────────────────┘   └──────────┘
src          └────┘    └────┘  └────┘ └────┘ └────────────────┘ └──────────┘└─────┘
typ          └────┘ └┘└────┘  └────┘ └────┘ └────────────────┘ └──────────┘└─────┘
doc          └────┘    └────┘  └────┘                                       └─────┘
txt          └────┘    └────┘  └────┘                                       └─────┘
par          └────┘    └────┘  └────┘                                       └─────┘
pid                   └────┘  └────┘                                       └────┘
st   ───────┘└────────────────────────────────────────────────────────────────────────┘└┘
488        { exact ⟨a, eq_of_sublist_of_length_eq s h ▸ subperm.refl _⟩ } },
id                    └────────────────────────┘    └──────────┘
src          └────┘  └┘└────────────────────────┘  └──────────┘└──┘
typ          └────┘ └┘└────────────────────────┘└──────────┘└──┘
doc          └────┘  └┘                                         └──┘
txt          └────┘  └┘                                         └──┘
par          └────┘  └┘                                         └──┘
pid                 └┘                                         └─┘
st   ──────────────────────────────────────────────────────────────────┘└──┘
489      { exact (IH $ nat.lt_of_succ_lt_succ h).imp
id                └┘   └────────────────────┘ 
src        └────┘    └────────────────────┘ └─────
typ        └────┘ └┘ └────────────────────┘└─────
doc        └────┘                           └─────
txt        └────┘                           └─────
par        └────┘                           └─────
pid                                        └─────
st   ────────────────────────────────────────────────
490          (λ a s, (swap _ _ _).subperm_right.1 $ (subperm_cons _).2 s) }
id                    └──┘                           └──────────┘
src  ───────┘  └────┘ └──┘└──────────────────────┘  └──────────┘└────┘ └┘
typ  ───────┘  └────┘ └──┘└──────────────────────┘  └──────────┘└────┘ └┘
doc  ───────┘  └────┘     └──────────────────────┘              └────┘ └┘
txt  ───────┘  └────┘     └──────────────────────┘              └────┘ └┘
par  ───────┘  └────┘     └──────────────────────┘              └────┘ └┘
pid  ───────┘  └────┘     └──────────────────────┘              └────┘ 
st   ────────────────────────────────────────────────────────────────────┘└─
491    end
st   ────┘
492  
493  theorem subperm_of_subset_nodup
494    {l₁ l₂ : list α} (d : nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~ l₂ :=
id              └──┘        └───┘ └┘       └┘  └┘    └┘ └─┘ └┘
src             └──┘         └───┘                       └─┘
typ             └──┘        └───┘ └┘       └┘  └┘    └┘ └─┘ └┘
doc                          └───┘                        └─┘
495  begin
st   └─────
496    induction d with a l₁' h d IH,
id               
src    └────────┘ └────────────────┘
typ    └────────┘└────────────────┘
doc    └────────┘ └────────────────┘
txt    └────────┘ └────────────────┘
par    └────────┘ └────────────────┘
pid              └───────────────┘
st   ──────────────────────────────┘└─
497    { exact ⟨nil, perm.nil, nil_sublist _⟩ },
id              └─┘  └──────┘  └─────────┘
src      └────┘ └─┘└┘└──────┘└┘└─────────┘└──┘
typ      └────┘ └─┘└┘└──────┘└┘└─────────┘└──┘
doc      └────┘    └┘        └┘           └──┘
txt      └────┘    └┘        └┘           └──┘
par      └────┘    └┘        └┘           └──┘
pid               └┘        └┘           └─┘
st   ───┘└───────────────────────────────────┘└┘
498    { cases forall_mem_cons.1 H with H₁ H₂,
id             └─────────────┘   
src      └────┘└─────────────┘└─┘ └─────────┘
typ      └────┘└─────────────┘└─┘└─────────┘
doc      └────┘               └─┘ └─────────┘
txt      └────┘               └─┘ └─────────┘
par      └────┘               └─┘ └─────────┘
pid                          └─┘ └─────────┘
st   ───────────────────────────────────────┘└─
499      simp at h,
src      └───────┘
typ      └───────┘
doc      └───────┘
txt      └───────┘
par      └───────┘
pid          └──┘
st   ────────────┘└─
500      exact cons_subperm_of_mem d h H₁ (IH H₂) }
id             └─────────────────┘   └┘  └┘ └┘
src      └────┘└─────────────────┘         └┘
typ      └────┘└─────────────────┘└┘ └┘└┘└┘
doc      └────┘                            └┘
txt      └────┘                            └┘
par      └────┘                            └┘
pid                                       
st   ────────────────────────────────────────────┘└─
501  end
st   ──┘
502  
503  theorem perm_ext {l₁ l₂ : list α} (d₁ : nodup l₁) (d₂ : nodup l₂) : l₁ ~ l₂ ↔ ∀a, a ∈ l₁ ↔ a ∈ l₂ :=
id                             └──┘         └───┘ └┘        └───┘ └┘    └┘  └┘       └┘    └┘
src                            └──┘          └───┘           └───┘                            
typ                            └──┘         └───┘ └┘        └───┘ └┘    └┘  └┘       └┘    └┘
doc                                          └───┘           └───┘          
504  ⟨λ p a, mem_of_perm p, λ H, subperm.antisymm
id         └─────────┘       └──────────────┘
src          └─────────┘         └──────────────┘
typ        └─────────┘       └──────────────┘
505    (subperm_of_subset_nodup d₁ (λ a, (H a).1))
id      └─────────────────────┘ └┘         
src     └─────────────────────┘               
typ     └─────────────────────┘ └┘         
506    (subperm_of_subset_nodup d₂ (λ a, (H a).2))⟩
id      └─────────────────────┘ └┘         
src     └─────────────────────┘               
typ     └─────────────────────┘ └┘         
507  
508  theorem perm_ext_sublist_nodup {l₁ l₂ l : list α} (d : nodup l)
id                                             └──┘        └───┘ 
src                                            └──┘         └───┘
typ                                            └──┘        └───┘ 
doc                                                         └───┘
509    (s₁ : l₁ <+ l) (s₂ : l₂ <+ l) : l₁ ~ l₂ ↔ l₁ = l₂ :=
id           └┘ └┘         └┘ └┘     └┘  └┘  └┘  └┘
src             └┘             └┘                 
typ          └┘ └┘         └┘ └┘     └┘  └┘  └┘  └┘
doc                                       
510  ⟨λ h, begin
id      
typ     
st         └─────
511    induction s₂ with l₂ l a s₂ IH l₂ l a s₂ IH generalizing l₁,
id               └┘
src    └────────┘  └─────────────────────────────────────────────┘
typ    └────────┘└┘└─────────────────────────────────────────────┘
doc    └────────┘  └─────────────────────────────────────────────┘
txt    └────────┘  └─────────────────────────────────────────────┘
par    └────────┘  └─────────────────────────────────────────────┘
pid               └────────────────────────────┘└──────────────┘
st   ────────────────────────────────────────────────────────────┘└─
512    { exact eq_nil_of_perm_nil h.symm },
id             └────────────────┘ └────┘
src      └────┘└────────────────┘└────┘
typ      └────┘└────────────────┘└────┘
doc      └────┘                        
txt      └────┘                        
par      └────┘                        
pid                                   
st   ───┘└──────────────────────────────┘└┘
513    { simp at d,
src      └───────┘
typ      └───────┘
doc      └───────┘
txt      └───────┘
par      └───────┘
pid          └──┘
st   ───┘└───────┘└─
514      cases s₁ with _ _ _ s₁ l₁ _ _ s₁,
id             └┘
src      └────┘  └──────────────────────┘
typ      └────┘└┘└──────────────────────┘
doc      └────┘  └──────────────────────┘
txt      └────┘  └──────────────────────┘
par      └────┘  └──────────────────────┘
pid             └──────────────────────┘
st   ───────────────────────────────────┘└─
515      { exact IH d.2 s₁ h },
id               └┘    └┘ 
src        └────┘   └─┘   
typ        └────┘└┘└─┘└┘
doc        └────┘   └─┘   
txt        └────┘   └─┘   
par        └────┘   └─┘   
pid                └─┘   
st   ─────┘└────────────────┘└┘
516      { apply d.1.elim,
id               
src        └────┘ └─────┘
typ        └────┘└─────┘
doc        └────┘ └─────┘
txt        └────┘ └─────┘
par        └────┘ └─────┘
pid              └────┘
st   ───────────────────┘└─
517        exact subset_of_subperm ⟨_, h.symm, s₂⟩ (mem_cons_self _ _) } },
id               └───────────────┘     └────┘  └┘   └───────────┘
src        └────┘└───────────────┘ └─┘└────┘└┘  └┘ └───────────┘└────┘
typ        └────┘└───────────────┘ └─┘└────┘└┘└┘└┘ └───────────┘└────┘
doc        └────┘                  └─┘      └┘  └┘              └────┘
txt        └────┘                  └─┘      └┘  └┘              └────┘
par        └────┘                  └─┘      └┘  └┘              └────┘
pid                               └─┘      └┘  └┘              └───┘
st   ─────────────────────────────────────────────────────────────────┘└──┘
518    { simp at d,
src      └───────┘
typ      └───────┘
doc      └───────┘
txt      └───────┘
par      └───────┘
pid          └──┘
st   ────────────┘└─
519      cases s₁ with _ _ _ s₁ l₁ _ _ s₁,
id             └┘
src      └────┘  └──────────────────────┘
typ      └────┘└┘└──────────────────────┘
doc      └────┘  └──────────────────────┘
txt      └────┘  └──────────────────────┘
par      └────┘  └──────────────────────┘
pid             └──────────────────────┘
st   ───────────────────────────────────┘└─
520      { apply d.1.elim,
id               
src        └────┘ └─────┘
typ        └────┘└─────┘
doc        └────┘ └─────┘
txt        └────┘ └─────┘
par        └────┘ └─────┘
pid              └────┘
st   ─────┘└────────────┘└─
521        exact subset_of_subperm ⟨_, h, s₁⟩ (mem_cons_self _ _) },
id               └───────────────┘       └┘   └───────────┘
src        └────┘└───────────────┘ └─┘ └┘  └┘ └───────────┘└────┘
typ        └────┘└───────────────┘ └─┘└┘└┘└┘ └───────────┘└────┘
doc        └────┘                  └─┘ └┘  └┘              └────┘
txt        └────┘                  └─┘ └┘  └┘              └────┘
par        └────┘                  └─┘ └┘  └┘              └────┘
pid                               └─┘ └┘  └┘              └───┘
st   ────────────────────────────────────────────────────────────┘└┘
522      { rw IH d.2 s₁ (perm_cons_inv h) } }
id            └┘    └┘  └───────────┘ 
src        └─┘   └─┘   └───────────┘ └┘
typ        └─┘└┘└─┘└┘ └───────────┘└┘
doc        └─┘   └─┘                 └┘
txt        └─┘   └─┘                 └┘
par        └─┘   └─┘                 └┘
pid             └─┘                 
st   ────────────────────────────────────┘└───
523  end, λ h, by rw h⟩
id                  
src               └─┘
typ              └─┘
doc               └─┘
txt               └─┘
par               └─┘
pid                 
st   ──┘         └───┘
524  
525  section
526  variable [decidable_eq α]
id             └──────────┘
src            └──────────┘
typ            └──────────┘
527  
528  -- attribute [congr]
529  theorem erase_perm_erase (a : α) {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id                                            └──┘        └┘  └┘
src                                            └──┘            
typ                                           └──┘        └┘  └┘
doc                                                            
530    l₁.erase a ~ l₂.erase a :=
id     └┘└────┘   └┘└────┘ 
src      └────┘      └────┘
typ    └┘└────┘   └┘└────┘ 
doc               
531  if h₁ : a ∈ l₁ then
id   └┘        └┘
src  └┘        
typ  └┘        └┘
532  have h₂ : a ∈ l₂, from perm_subset p h₁,
id               └┘       └─────────┘  └┘
src                        └─────────┘
typ              └┘       └─────────┘  └┘
533  perm_cons_inv $ trans (perm_erase h₁).symm $ trans p (perm_erase h₂)
id   └───────────┘   └───┘  └────────┘ └┘ └──┘    └───┘   └────────┘ └┘
src  └───────────┘   └───┘  └────────┘    └──┘    └───┘    └────────┘
typ  └───────────┘   └───┘  └────────┘ └┘ └──┘    └───┘   └────────┘ └┘
534  else
535  have h₂ : a ∉ l₂, from mt (mem_of_perm p).2 h₁,
id   └──┘        └┘       └┘  └─────────┘    └┘
src  └──┘                  └┘  └─────────┘   
typ  └──┘        └┘       └┘  └─────────┘    └┘
536  by rw [erase_of_not_mem h₁, erase_of_not_mem h₂]; exact p
id          └──────────────┘ └┘  └──────────────┘ └┘         
src     └──┘└──────────────┘  └┘└──────────────┘    └────┘ 
typ     └──┘└──────────────┘└┘└┘└──────────────┘└┘  └────┘
doc     └──┘                  └┘                    └────┘ 
txt     └──┘                  └┘                    └────┘ 
par     └──┘                  └┘                    └────┘ 
pid       └┘                  └┘                          
st     └──────────────────────┘└───────────────────┘└─────────
537  
src  
typ  
doc  
txt  
par  
pid  
st   
538  theorem erase_subperm (a : α) (l : list α) : l.erase a <+~ l :=
id                                     └──┘     └────┘  └─┘ 
src                                     └──┘       └────┘   └─┘
typ                                    └──┘     └────┘  └─┘ 
doc                                                         └─┘
539  ⟨l.erase a, perm.refl _, erase_sublist _ _⟩
id    └────┘   └───────┘    └───────────┘
src    └────┘    └───────┘    └───────────┘
typ   └────┘   └───────┘    └───────────┘
540  
541  theorem erase_subperm_erase {l₁ l₂ : list α} (a : α) (h : l₁ <+~ l₂) : l₁.erase a <+~ l₂.erase a :=
id                                        └──┘               └┘ └─┘ └┘    └┘└────┘  └─┘ └┘└────┘ 
src                                       └──┘                    └─┘         └────┘   └─┘   └────┘
typ                                       └──┘               └┘ └─┘ └┘    └┘└────┘  └─┘ └┘└────┘ 
doc                                                               └─┘                  └─┘
542  let ⟨l, hp, hs⟩ := h in ⟨l.erase a, erase_perm_erase _ hp, erase_sublist_erase _ hs⟩
id   └─┘    └┘  └┘           └────┘   └──────────────┘       └─────────────────┘
src                            └────┘    └──────────────┘       └─────────────────┘
typ  └─┘    └┘  └┘           └────┘   └──────────────┘       └─────────────────┘
543  
544  theorem perm_diff_left {l₁ l₂ : list α} (t : list α) (h : l₁ ~ l₂) : l₁.diff t ~ l₂.diff t :=
id                                   └──┘        └──┘        └┘  └┘    └┘└───┘   └┘└───┘ 
src                                  └──┘         └──┘                     └───┘      └───┘
typ                                  └──┘        └──┘        └┘  └┘    └┘└───┘   └┘└───┘ 
doc                                                                                
545  by induction t generalizing l₁ l₂ h; simp [*, erase_perm_erase]
id                                                └──────────────┘
src     └────────┘ └───────────────────┘  └───────┘└──────────────┘└─
typ     └────────┘└───────────────────┘  └───────┘└──────────────┘└─
doc     └────────┘ └───────────────────┘  └───────┘                └─
txt     └────────┘ └───────────────────┘  └───────┘                └─
par     └────────┘ └───────────────────┘  └───────┘                └─
pid               └──────────────────┘      └──┘                
st     └─────────────────────────────────────────────────────────────
546  
src  
typ  
doc  
txt  
par  
pid  
st   
547  theorem perm_diff_right (l : list α) {t₁ t₂ : list α} (h : t₁ ~ t₂) : l.diff t₁ = l.diff t₂ :=
id                                └──┘            └──┘        └┘  └┘    └───┘ └┘  └───┘ └┘
src                               └──┘             └──┘                    └───┘      └───┘
typ                               └──┘            └──┘        └┘  └┘    └───┘ └┘  └───┘ └┘
doc                                                                
548  by induction h generalizing l; simp [*, erase_perm_erase, erase_comm]
id                                          └──────────────┘  └────────┘
src     └────────┘ └─────────────┘  └───────┘└──────────────┘└┘└────────┘└─
typ     └────────┘└─────────────┘  └───────┘└──────────────┘└┘└────────┘└─
doc     └────────┘ └─────────────┘  └───────┘                └┘          └─
txt     └────────┘ └─────────────┘  └───────┘                └┘          └─
par     └────────┘ └─────────────┘  └───────┘                └┘          └─
pid               └────────────┘      └──┘                └┘          
st     └───────────────────────────────────────────────────────────────────
549    <|> exact (ih_1 _).trans (ih_2 _)
src  ─┘    └────┘     └────────┘     └───
typ  ─┘    └────┘     └────────┘     └───
doc  ─┘    └────┘     └────────┘     └───
txt  ─┘    └────┘     └────────┘     └───
par  ─┘    └────┘     └────────┘     └───
pid  ─┘              └────────┘     └─┘
st   ────────────────────────────────────
550  
src  
typ  
doc  
txt  
par  
pid  
st   
551  theorem subperm_cons_diff {a : α} : ∀ {l₁ l₂ : list α}, (a :: l₁).diff l₂ <+~ a :: l₁.diff l₂
id                                                └──┘      └┘ └┘ └──┘  └┘ └─┘  └┘ └┘└───┘ └┘
src                                                 └──┘        └┘    └──┘     └─┘   └┘   └───┘
typ                                               └──┘      └┘ └┘ └──┘  └┘ └─┘  └┘ └┘└───┘ └┘
doc                                                                            └─┘
552  | l₁ []      := ⟨a::l₁, by simp⟩
id     └┘ └┘          └┘
src       └┘           └┘       └──┘
typ    └┘ └┘          └┘       └──┘
doc                             └──┘
txt                             └──┘
par                             └──┘
st                             └───┘
553  | l₁ (b::l₂) :=
id          └┘
src         └┘
typ         └┘
554  begin
st   └─────
555    repeat {rw diff_cons},
id                └───────┘
src    └──────┘└─┘└───────┘
typ    └──────┘└─┘└───────┘
doc    └──────┘└─┘         
txt    └──────┘└─┘         
par    └──────┘└─┘         
pid          └───┘         
st   ─────────────────────┘└┘
556    by_cases heq : a = b,
id                      
src    └───────┘   └─┘ 
typ    └───────┘   └─┘
doc    └───────┘   └─┘  
txt    └───────┘   └─┘  
par    └───────┘   └─┘  
pid               └─┘  
st   ─────────────────────┘└─
557    { by_cases b ∈ l₁,
id                  └┘
src      └───────┘ 
typ      └───────┘└┘
doc      └───────┘  
txt      └───────┘  
par      └───────┘  
pid                
st   ───┘└─────────────┘└─
558      { rw perm.subperm_right, apply subperm_cons_diff,
id            └────────────────┘
src        └─┘└────────────────┘  └────┘
typ        └─┘└────────────────┘  └────┘
doc        └─┘                    └────┘
txt        └─┘                    └────┘
par        └─┘                    └────┘
pid                                   
st   ─────┘└───────────────────┘└───────────────────────┘└─
559        simp [perm_diff_left, heq, perm_erase h] },
id               └────────────┘  └─┘  └────────┘ 
src        └────┘└────────────┘└┘└─┘└┘└────────┘ └┘
typ        └────┘└────────────┘└┘└─┘└┘└────────┘└┘
doc        └────┘              └┘   └┘           └┘
txt        └────┘              └┘   └┘           └┘
par        └────┘              └┘   └┘           └┘
pid                          └┘   └┘           
st   ──────────────────────────────────────────────┘└┘
560      { simp [subperm_of_sublist, sublist.cons, h, heq] } },
id               └────────────────┘  └──────────┘    └─┘
src        └────┘└────────────────┘└┘└──────────┘└┘ └┘└─┘└┘
typ        └────┘└────────────────┘└┘└──────────┘└┘└┘└─┘└┘
doc        └────┘                  └┘            └┘ └┘   └┘
txt        └────┘                  └┘            └┘ └┘   └┘
par        └────┘                  └┘            └┘ └┘   └┘
pid                              └┘            └┘ └┘   
st   ─────────────────────────────────────────────────────┘└──┘
561    { simp [heq, subperm_cons_diff] }
id             └─┘
src      └────┘└─┘└┘                 └┘
typ      └────┘└─┘└┘└───────────────┘└┘
doc      └────┘   └┘                 └┘
txt      └────┘   └┘                 └┘
par      └────┘   └┘                 └┘
pid             └┘                 
st   ─────────────────────────────────┘└─
562  end
st   ──┘
563  
564  theorem subset_cons_diff {a : α} {l₁ l₂ : list α} : (a :: l₁).diff l₂ ⊆ a :: l₁.diff l₂ :=
id                                            └──┘       └┘ └┘ └──┘  └┘   └┘ └┘└───┘ └┘
src                                            └──┘         └┘    └──┘        └┘   └───┘
typ                                           └──┘       └┘ └┘ └──┘  └┘   └┘ └┘└───┘ └┘
565  subset_of_subperm subperm_cons_diff
id   └───────────────┘ └───────────────┘
src  └───────────────┘ └───────────────┘
typ  └───────────────┘ └───────────────┘
566  
567  theorem perm_bag_inter_left {l₁ l₂ : list α} (t : list α) (h : l₁ ~ l₂) : l₁.bag_inter t ~ l₂.bag_inter t :=
id                                        └──┘        └──┘        └┘  └┘    └┘└────────┘   └┘└────────┘ 
src                                       └──┘         └──┘                     └────────┘      └────────┘
typ                                       └──┘        └──┘        └┘  └┘    └┘└────────┘   └┘└────────┘ 
doc                                                                                          
568  begin
st   └─────
569    induction h with x _ _ _ _ x y _ _ _ _ _ _ ih_1 ih_2 generalizing t, {simp},
id               
src    └────────┘ └──────────────────────────────────────────────────────┘   └──┘
typ    └────────┘└──────────────────────────────────────────────────────┘   └──┘
doc    └────────┘ └──────────────────────────────────────────────────────┘   └──┘
txt    └────────┘ └──────────────────────────────────────────────────────┘   └──┘
par    └────────┘ └──────────────────────────────────────────────────────┘   └──┘
pid              └──────────────────────────────────────┘└─────────────┘
st   ────────────────────────────────────────────────────────────────────┘└─────┘└┘
570    { by_cases x ∈ t; simp [*, skip] },
id                             └──┘
src      └───────┘    └───────┘└──┘└┘
typ      └───────┘  └───────┘└──┘└┘
doc      └───────┘     └───────┘    └┘
txt      └───────┘     └───────┘    └┘
par      └───────┘     └───────┘    └┘
pid                       └──┘    
st   ───┘└─────────────────────────────┘└┘
571    { by_cases x = y, {simp [h]},
id                           
src      └───────┘     └────┘ 
typ      └───────┘   └────┘
doc      └───────┘      └────┘ 
txt      └───────┘      └────┘ 
par      └───────┘      └────┘ 
pid                         
st   ───┘└────────────┘└─────────┘└┘
572      by_cases xt : x ∈ t; by_cases yt : y ∈ t,
id                                           
src      └───────┘  └─┘     └───────┘  └─┘  
typ      └───────┘  └─┘   └───────┘  └─┘ 
doc      └───────┘  └─┘     └───────┘  └─┘  
txt      └───────┘  └─┘     └───────┘  └─┘  
par      └───────┘  └─┘     └───────┘  └─┘  
pid                └─┘               └─┘  
st   ───────────────────────────────────────────┘└─
573      { simp [xt, yt, mem_erase_of_ne h, mem_erase_of_ne (ne.symm h), erase_comm, swap] },
id               └┘  └┘  └─────────────┘   └─────────────┘  └─────┘    └────────┘  └──┘
src        └────┘  └┘  └┘└─────────────┘ └┘└─────────────┘ └─────┘ └─┘└────────┘└┘└──┘└┘
typ        └────┘└┘└┘└┘└┘└─────────────┘└┘└─────────────┘ └─────┘└─┘└────────┘└┘└──┘└┘
doc        └────┘  └┘  └┘                └┘                        └─┘          └┘    └┘
txt        └────┘  └┘  └┘                └┘                        └─┘          └┘    └┘
par        └────┘  └┘  └┘                └┘                        └─┘          └┘    └┘
pid              └┘  └┘                └┘                        └─┘          └┘    
st   ─────┘└──────────────────────────────────────────────────────────────────────────────┘└┘
574      { simp [xt, yt, mt mem_of_mem_erase, skip] },
id               └┘  └┘  └┘ └──────────────┘  └──┘
src        └────┘  └┘  └┘└┘└──────────────┘└┘└──┘└┘
typ        └────┘└┘└┘└┘└┘└┘└──────────────┘└┘└──┘└┘
doc        └────┘  └┘  └┘                  └┘    └┘
txt        └────┘  └┘  └┘                  └┘    └┘
par        └────┘  └┘  └┘                  └┘    └┘
pid              └┘  └┘                  └┘    
st   ─────┘└───────────────────────────────────────┘└┘
575      { simp [xt, yt, mt mem_of_mem_erase, skip] },
id               └┘  └┘  └┘ └──────────────┘  └──┘
src        └────┘  └┘  └┘└┘└──────────────┘└┘└──┘└┘
typ        └────┘└┘└┘└┘└┘└┘└──────────────┘└┘└──┘└┘
doc        └────┘  └┘  └┘                  └┘    └┘
txt        └────┘  └┘  └┘                  └┘    └┘
par        └────┘  └┘  └┘                  └┘    └┘
pid              └┘  └┘                  └┘    
st   ─────┘└───────────────────────────────────────┘└┘
576      { simp [xt, yt] } },
id               └┘  └┘
src        └────┘  └┘  └┘
typ        └────┘└┘└┘└┘└┘
doc        └────┘  └┘  └┘
txt        └────┘  └┘  └┘
par        └────┘  └┘  └┘
pid              └┘  
st   ───────────────────┘└──┘
577    { exact (ih_1 _).trans (ih_2 _) }
id              └──┘           └──┘
src      └────┘     └────────┘     └──┘
typ      └────┘ └──┘└────────┘ └──┘└──┘
doc      └────┘     └────────┘     └──┘
txt      └────┘     └────────┘     └──┘
par      └────┘     └────────┘     └──┘
pid                └────────┘     └─┘
st   ─────────────────────────────────┘└─
578  end
st   ──┘
579  
580  theorem perm_bag_inter_right (l : list α) {t₁ t₂ : list α} (p : t₁ ~ t₂) : l.bag_inter t₁ = l.bag_inter t₂ :=
id                                     └──┘            └──┘        └┘  └┘    └────────┘ └┘  └────────┘ └┘
src                                    └──┘             └──┘                    └────────┘      └────────┘
typ                                    └──┘            └──┘        └┘  └┘    └────────┘ └┘  └────────┘ └┘
doc                                                                     
581  begin
st   └─────
582    induction l with a l IH generalizing t₁ t₂ p, {simp},
id               
src    └────────┘ └───────────────────────────────┘   └──┘
typ    └────────┘└───────────────────────────────┘   └──┘
doc    └────────┘ └───────────────────────────────┘   └──┘
txt    └────────┘ └───────────────────────────────┘   └──┘
par    └────────┘ └───────────────────────────────┘   └──┘
pid              └─────────┘└───────────────────┘
st   ─────────────────────────────────────────────┘└─────┘└┘
583    by_cases a ∈ t₁,
id                └┘
src    └───────┘ 
typ    └───────┘└┘
doc    └───────┘  
txt    └───────┘  
par    └───────┘  
pid              
st   ────────────────┘└─
584    { simp [h, (mem_of_perm p).1 h, IH (erase_perm_erase _ p)] },
id                └─────────┘       └┘  └──────────────┘   
src      └────┘ └┘ └─────────┘ └──┘ └┘   └──────────────┘└─┘ └─┘
typ      └────┘└┘ └─────────┘└──┘└┘└┘ └──────────────┘└─┘└─┘
doc      └────┘ └┘             └──┘ └┘                   └─┘ └─┘
txt      └────┘ └┘             └──┘ └┘                   └─┘ └─┘
par      └────┘ └┘             └──┘ └┘                   └─┘ └─┘
pid           └┘             └──┘ └┘                   └─┘ └┘
st   ───┘└───────────────────────────────────────────────────────┘└┘
585    { simp [h, mt (mem_of_perm p).2 h, IH p] }
id               └┘  └─────────┘       └┘ 
src      └────┘ └┘└┘ └─────────┘ └──┘ └┘   └┘
typ      └────┘└┘└┘ └─────────┘└──┘└┘└┘└┘
doc      └────┘ └┘               └──┘ └┘   └┘
txt      └────┘ └┘               └──┘ └┘   └┘
par      └────┘ └┘               └──┘ └┘   └┘
pid           └┘               └──┘ └┘   
st   ──────────────────────────────────────────┘└─
586  end
st   ──┘
587  
588  theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : list α} : a::l₁ ~ l₂ ↔ a ∈ l₂ ∧ l₁ ~ l₂.erase a :=
id                                                    └──┘     └┘└┘  └┘    └┘  └┘  └┘└────┘ 
src                                                    └──┘       └┘                     └────┘
typ                                                   └──┘     └┘└┘  └┘    └┘  └┘  └┘└────┘ 
doc                                                                                      
589  ⟨λ h, have a ∈ l₂, from perm_subset h (mem_cons_self a l₁),
id               └┘       └─────────┘   └───────────┘  └┘
src                         └─────────┘    └───────────┘
typ              └┘       └─────────┘   └───────────┘  └┘
590        ⟨this, perm_cons_inv $ h.trans $ perm_erase this⟩,
id          └──┘  └───────────┘   └────┘   └────────┘ └──┘
src               └───────────┘    └────┘   └────────┘
typ         └──┘  └───────────┘   └────┘   └────────┘ └──┘
591   λ ⟨m, h⟩, trans (skip a h) (perm_erase m).symm⟩
id           └───┘  └──┘      └────────┘   └──┘
src             └───┘  └──┘       └────────┘   └──┘
typ          └───┘  └──┘      └────────┘   └──┘
592  
593  theorem perm_iff_count {l₁ l₂ : list α} : l₁ ~ l₂ ↔ ∀ a, count a l₁ = count a l₂ :=
id                                   └──┘     └┘  └┘      └───┘  └┘  └───┘  └┘
src                                  └──┘                   └───┘       └───┘
typ                                  └──┘     └┘  └┘      └───┘  └┘  └───┘  └┘
doc                                                          └───┘        └───┘
594  ⟨perm_count, λ H, begin
id    └────────┘    
src   └────────┘
typ   └────────┘    
st                     └─────
595    induction l₁ with a l₁ IH generalizing l₂,
id               └┘
src    └────────┘  └───────────────────────────┘
typ    └────────┘└┘└───────────────────────────┘
doc    └────────┘  └───────────────────────────┘
txt    └────────┘  └───────────────────────────┘
par    └────────┘  └───────────────────────────┘
pid               └──────────┘└──────────────┘
st   ──────────────────────────────────────────┘└─
596    { cases l₂ with b l₂, {refl},
id             └┘
src      └────┘  └────────┘   └──┘
typ      └────┘└┘└────────┘   └──┘
doc      └────┘  └────────┘   └──┘
txt      └────┘  └────────┘   └──┘
par      └────┘  └────────┘   └──┘
pid             └────────┘
st   ───┘└────────────────┘└─────┘└┘
597      specialize H b, simp at H, contradiction },
id                   
src      └─────────┘    └───────┘  └────────────┘
typ      └─────────┘  └───────┘  └────────────┘
doc      └─────────┘    └───────┘  └────────────┘
txt      └─────────┘    └───────┘  └────────────┘
par      └─────────┘    └───────┘  └────────────┘
pid                        └──┘               
st   ─────────────────┘└─────────┘└──────────────┘└┘
598    { have : a ∈ l₂ := count_pos.1 (by rw ← H; simp; apply nat.succ_pos),
id                └┘    └───────┘            
src      └─────┘   └──┘└───────┘└─┘   └───┘ └┘└──┘└┘└────┘            
typ      └─────┘└┘└──┘└───────┘└─┘   └───┘└┘└──┘└┘└────┘            
doc      └─────┘    └──┘         └─┘   └───┘ └┘└──┘└┘└────┘            
txt      └─────┘    └──┘         └─┘   └───┘ └┘└──┘└┘└────┘            
par      └─────┘    └──┘         └─┘   └───┘ └┘└──┘└┘└────┘            
pid      └───┘└┘    └──┘         └─┘   └────┘ └────────────┘            
st   ───────────────────────────────────┘└───────────────────────────────┘└─
599      refine trans (skip a $ IH $ λ b, _) (perm_erase this).symm,
id              └───┘  └──┘    └┘            └────────┘ └──┘
src      └─────┘└───┘ └──┘      └─────┘ └────────┘    └────┘
typ      └─────┘└───┘ └──┘ └┘  └─────┘ └────────┘└──┘└────┘
doc      └─────┘                └─────┘               └────┘
txt      └─────┘                └─────┘               └────┘
par      └─────┘                └─────┘               └────┘
pid                            └─────┘               └───┘
st   ─────────────────────────────────────────────────────────────┘└─
600      specialize H b,
id                   
src      └─────────┘ 
typ      └─────────┘
doc      └─────────┘ 
txt      └─────────┘ 
par      └─────────┘ 
pid                 
st   ─────────────────┘└─
601      rw perm_count (perm_erase this) at H,
id          └────────┘  └────────┘ └──┘
src      └─┘└────────┘ └────────┘    └────┘
typ      └─┘└────────┘ └────────┘└──┘└────┘
doc      └─┘                         └────┘
txt      └─┘                         └────┘
par      └─┘                         └────┘
pid                                 └───┘
st   ───────────────────────────────────────┘└─
602      by_cases b = a; simp [h] at H ⊢; assumption }
id                          
src      └───────┘    └────┘ └──────┘  └─────────┘
typ      └───────┘  └────┘└──────┘  └─────────┘
doc      └───────┘     └────┘ └──────┘  └─────────┘
txt      └───────┘     └────┘ └──────┘  └─────────┘
par      └───────┘     └────┘ └──────┘  └─────────┘
pid                        └────┘            
st   ───────────────────────────────────────────────┘└─
603  end⟩
st   ──┘
604  
605  instance decidable_perm : ∀ (l₁ l₂ : list α), decidable (l₁ ~ l₂)
id                                       └──┘    └───────┘  └┘  └┘
src                                       └──┘     └───────┘     
typ                                      └──┘    └───────┘  └┘  └┘
doc                                                              
606  | []      []      := is_true $ perm.refl _
id     └┘      └┘         └─────┘   └───────┘
src    └┘      └┘         └─────┘   └───────┘
typ    └┘      └┘         └─────┘   └───────┘
607  | []      (b::l₂) := is_false $ λ h, by have := eq_nil_of_perm_nil h; contradiction
id     └┘        └┘       └──────┘                  └────────────────┘ 
src    └┘        └┘       └──────┘           └──────┘└────────────────┘   └────────────┘
typ    └┘        └┘       └──────┘          └──────┘└────────────────┘  └────────────┘
doc                                          └──────┘                     └────────────┘
txt                                          └──────┘                     └────────────┘
par                                          └──────┘                     └────────────┘
pid                                          └───┘└─┘                                  
st                                          └───────────────────────────────────────────┘
608  | (a::l₁) l₂      := by haveI := decidable_perm l₁ (l₂.erase a);
id       └┘                           └────────────┘ └┘  └──────┘ 
src      └┘                  └───────┘                 └──────┘ 
typ      └┘                  └───────┘└────────────┘└┘ └──────┘
doc                          └───────┘                          
txt                          └───────┘                          
par                          └───────┘                          
pid                               └─┘                          
st                          └─────────────────────────────────────────
609                          exact decidable_of_iff' _ cons_perm_iff_perm_erase
id                                 └───────────────┘   └──────────────────────┘
src                          └────┘└───────────────┘└─┘└──────────────────────┘
typ                          └────┘└───────────────┘└─┘└──────────────────────┘
doc                          └────┘                 └─┘                        
txt                          └────┘                 └─┘                        
par                          └────┘                 └─┘                        
pid                                                └─┘                        
st   ───────────────────────────────────────────────────────────────────────────
610  
src  
typ  
doc  
txt  
par  
pid  
st   
611  -- @[congr]
src  ───────────┘
typ  ───────────┘
doc  ───────────┘
txt  ───────────┘
par  ───────────┘
pid  ───────────┘
st   ───────────┘
612  theorem perm_erase_dup_of_perm {l₁ l₂ : list α} (p : l₁ ~ l₂) :
id                                           └──┘        └┘  └┘
src                                          └──┘            
typ                                          └──┘        └┘  └┘
doc                                                          
613    erase_dup l₁ ~ erase_dup l₂ :=
id     └───────┘ └┘  └───────┘ └┘
src    └───────┘     └───────┘
typ    └───────┘ └┘  └───────┘ └┘
doc    └───────┘     └───────┘
614  perm_iff_count.2 $ λ a,
id   └────────────┘      
src  └────────────┘
typ  └────────────┘      
615  if h : a ∈ l₁
id   └┘       └┘
src  └┘       
typ  └┘       └┘
616  then by simp [nodup_erase_dup, h, perm_subset p h]
id                 └─────────────┘    └─────────┘  
src          └────┘└─────────────┘└┘ └┘└─────────┘  └┘
typ          └────┘└─────────────┘└┘└┘└─────────┘└┘
doc          └────┘               └┘ └┘             └┘
txt          └────┘               └┘ └┘             └┘
par          └────┘               └┘ └┘             └┘
pid                             └┘ └┘             
st          └──────────────────────────────────────────┘
617  else by simp [h, mt (mem_of_perm p).2 h]
id                   └┘  └─────────┘     
src          └────┘ └┘└┘ └─────────┘ └──┘ └─
typ          └────┘└┘└┘ └─────────┘└──┘└─
doc          └────┘ └┘               └──┘ └─
txt          └────┘ └┘               └──┘ └─
par          └────┘ └┘               └──┘ └─
pid               └┘               └──┘ 
st          └─────────────────────────────────
618  
src  
typ  
doc  
txt  
par  
pid  
st   
619  -- attribute [congr]
src  ────────────────────┘
typ  ────────────────────┘
doc  ────────────────────┘
txt  ────────────────────┘
par  ────────────────────┘
pid  ────────────────────┘
st   ────────────────────┘
620  theorem perm_insert (a : α)
id                            
typ                           
621    {l₁ l₂ : list α} (p : l₁ ~ l₂) : insert a l₁ ~ insert a l₂ :=
id              └──┘        └┘  └┘    └────┘  └┘  └────┘  └┘
src             └──┘                   └────┘       └────┘
typ             └──┘        └┘  └┘    └────┘  └┘  └────┘  └┘
doc                                                
622  if h : a ∈ l₁
id   └┘       └┘
src  └┘       
typ  └┘       └┘
623  then by simpa [h, perm_subset p h] using p
id                    └─────────┘          
src          └─────┘ └┘└─────────┘  └──────┘ 
typ          └─────┘└┘└─────────┘└──────┘
doc          └─────┘ └┘             └──────┘ 
txt          └─────┘ └┘             └──────┘ 
par          └─────┘ └┘             └──────┘ 
pid                └┘             └────┘ 
st          └──────────────────────────────────┘
624  else by simpa [h, mt (mem_of_perm p).2 h] using skip a p
id                    └┘  └─────────┘             └──┘  
src          └─────┘ └┘└┘ └─────────┘ └──┘ └──────┘└──┘  
typ          └─────┘└┘└┘ └─────────┘└──┘└──────┘└──┘
doc          └─────┘ └┘               └──┘ └──────┘      
txt          └─────┘ └┘               └──┘ └──────┘      
par          └─────┘ └┘               └──┘ └──────┘      
pid                └┘               └──┘ └────┘      
st          └─────────────────────────────────────────────────
625  
src  
typ  
doc  
txt  
par  
pid  
st   
626  theorem perm_insert_swap (x y : α) (l : list α) :
id                                          └──┘ 
src                                          └──┘
typ                                         └──┘ 
627    insert x (insert y l) ~ insert y (insert x l) :=
id     └────┘   └────┘     └────┘   └────┘  
src    └────┘    └────┘       └────┘    └────┘
typ    └────┘   └────┘     └────┘   └────┘  
doc                          
628  begin
st   └─────
629    by_cases xl : x ∈ l; by_cases yl : y ∈ l; simp [xl, yl],
id                                                └┘  └┘
src    └───────┘  └─┘    └───────┘  └─┘     └────┘  └┘  
typ    └───────┘  └─┘  └───────┘  └─┘   └────┘└┘└┘└┘
doc    └───────┘  └─┘     └───────┘  └─┘     └────┘  └┘  
txt    └───────┘  └─┘     └───────┘  └─┘     └────┘  └┘  
par    └───────┘  └─┘     └───────┘  └─┘     └────┘  └┘  
pid              └─┘               └─┘           └┘  
st   ────────────────────────────────────────────────────────┘└─
630    by_cases xy : x = y, { simp [xy] },
id                               └┘
src    └───────┘  └─┘      └────┘  └┘
typ    └───────┘  └─┘    └────┘└┘└┘
doc    └───────┘  └─┘       └────┘  └┘
txt    └───────┘  └─┘       └────┘  └┘
par    └───────┘  └─┘       └────┘  └┘
pid              └─┘             
st   ────────────────────┘└──┘└────────┘└┘
631    simp [not_mem_cons_of_ne_of_not_mem xy xl,
id           └───────────────────────────┘ └┘ └┘
src    └────┘└───────────────────────────┘    └─
typ    └────┘└───────────────────────────┘└┘└┘└─
doc    └────┘                                 └─
txt    └────┘                                 └─
par    └────┘                                 └─
pid                                         └─
st   ─────────────────────────────────────────────
632          not_mem_cons_of_ne_of_not_mem (ne.symm xy) yl],
id           └───────────────────────────┘  └─────┘ └┘  └┘
src  ───────┘└───────────────────────────┘ └─────┘  └┘  
typ  ───────┘└───────────────────────────┘ └─────┘└┘└┘└┘
doc  ───────┘                                       └┘  
txt  ───────┘                                       └┘  
par  ───────┘                                       └┘  
pid  ───────┘                                       └┘  
st   ─────────────────────────────────────────────────────┘└─
633    constructor
src    └──────────┘
typ    └──────────┘
doc    └──────────┘
txt    └──────────┘
par    └──────────┘
pid               
st   ─────────────┘
634  end
st   └─┘
635  
636  theorem perm_union_left {l₁ l₂ : list α} (t₁ : list α) (h : l₁ ~ l₂) : l₁ ∪ t₁ ~ l₂ ∪ t₁ :=
id                                    └──┘         └──┘        └┘  └┘    └┘  └┘  └┘  └┘
src                                   └──┘          └──┘                              
typ                                   └──┘         └──┘        └┘  └┘    └┘  └┘  └┘  └┘
doc                                                                                
637  begin
st   └─────
638    induction h with a _ _ _ ih _ _ _ _ _ _ _ _ ih_1 ih_2; try {simp},
id               
src    └────────┘ └────────────────────────────────────────┘  └───┘└──┘
typ    └────────┘└────────────────────────────────────────┘  └───┘└──┘
doc    └────────┘ └────────────────────────────────────────┘  └───┘└──┘
txt    └────────┘ └────────────────────────────────────────┘  └───┘└──┘
par    └────────┘ └────────────────────────────────────────┘  └───┘└──┘
pid              └───────────────────────────────────────┘     └─────┘
st   ─────────────────────────────────────────────────────────────┘└──┘└┘
639    { exact perm_insert a ih },
id             └─────────┘  └┘
src      └────┘└─────────┘   
typ      └────┘└─────────┘└┘
doc      └────┘              
txt      └────┘              
par      └────┘              
pid                         
st   ───┘└─────────────────────┘└┘
640    { apply perm_insert_swap },
id             └──────────────┘
src      └────┘└──────────────┘
typ      └────┘└──────────────┘
doc      └────┘                
txt      └────┘                
par      └────┘                
pid                           
st   ───┘└─────────────────────┘└┘
641    { exact ih_1.trans ih_2 }
id             └────────┘ └──┘
src      └────┘└────────┘    
typ      └────┘└────────┘└──┘
doc      └────┘              
txt      └────┘              
par      └────┘              
pid                         
st   ─────────────────────────┘└─
642  end
st   ──┘
643  
644  theorem perm_union_right (l : list α) {t₁ t₂ : list α} (h : t₁ ~ t₂) : l ∪ t₁ ~ l ∪ t₂ :=
id                                 └──┘            └──┘        └┘  └┘      └┘    └┘
src                                └──┘             └──┘                            
typ                                └──┘            └──┘        └┘  └┘      └┘    └┘
doc                                                                               
645  by induction l; simp [*, perm_insert]
id                           └─────────┘
src     └────────┘   └───────┘└─────────┘└─
typ     └────────┘  └───────┘└─────────┘└─
doc     └────────┘   └───────┘           └─
txt     └────────┘   └───────┘           └─
par     └────────┘   └───────┘           └─
pid                     └──┘           
st     └───────────────────────────────────
646  
src  
typ  
doc  
txt  
par  
pid  
st   
647  -- @[congr]
src  ───────────┘
typ  ───────────┘
doc  ───────────┘
txt  ───────────┘
par  ───────────┘
pid  ───────────┘
st   ───────────┘
648  theorem perm_union {l₁ l₂ t₁ t₂ : list α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁ ∪ t₁ ~ l₂ ∪ t₂ :=
id                                     └──┘         └┘  └┘        └┘  └┘    └┘  └┘  └┘  └┘
src                                    └──┘                                             
typ                                    └──┘         └┘  └┘        └┘  └┘    └┘  └┘  └┘  └┘
doc                                                                                  
649  trans (perm_union_left t₁ p₁) (perm_union_right l₂ p₂)
id   └───┘  └─────────────┘ └┘ └┘   └──────────────┘ └┘ └┘
src  └───┘  └─────────────┘         └──────────────┘
typ  └───┘  └─────────────┘ └┘ └┘   └──────────────┘ └┘ └┘
650  
651  theorem perm_inter_left {l₁ l₂ : list α} (t₁ : list α) : l₁ ~ l₂ → l₁ ∩ t₁ ~ l₂ ∩ t₁ :=
id                                    └──┘         └──┘     └┘  └┘   └┘  └┘  └┘  └┘
src                                   └──┘          └──┘                          
typ                                   └──┘         └──┘     └┘  └┘   └┘  └┘  └┘  └┘
doc                                                                            
652  perm_filter _
id   └─────────┘
src  └─────────┘
typ  └─────────┘
653  
654  theorem perm_inter_right (l : list α) {t₁ t₂ : list α} (p : t₁ ~ t₂) : l ∩ t₁ = l ∩ t₂ :=
id                                 └──┘            └──┘        └┘  └┘      └┘    └┘
src                                └──┘             └──┘                            
typ                                └──┘            └──┘        └┘  └┘      └┘    └┘
doc                                                                 
655  by dsimp [(∩), list.inter]; congr; funext a; rw [mem_of_perm p]
id                  └────────┘                        └─────────┘ 
src     └─────┘ └──┘└────────┘  └───┘  └──────┘  └──┘└─────────┘ └─
typ     └─────┘ └──┘└────────┘  └───┘  └──────┘  └──┘└─────────┘└─
doc     └─────┘ └──┘                   └──────┘  └──┘            └─
txt     └─────┘ └──┘            └───┘  └──────┘  └──┘            └─
par     └─────┘ └──┘            └───┘  └──────┘  └──┘            └─
pid           └──┘                         └┘    └┘            
st     └─────────────────────────────────────────────┘└───────────┘
656  
src  
typ  
doc  
txt  
par  
pid  
st   
657  -- @[congr]
src  ───────────┘
typ  ───────────┘
doc  ───────────┘
txt  ───────────┘
par  ───────────┘
pid  ───────────┘
st   ───────────┘
658  theorem perm_inter {l₁ l₂ t₁ t₂ : list α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁ ∩ t₁ ~ l₂ ∩ t₂ :=
id                                     └──┘         └┘  └┘        └┘  └┘    └┘  └┘  └┘  └┘
src                                    └──┘                                             
typ                                    └──┘         └┘  └┘        └┘  └┘    └┘  └┘  └┘  └┘
doc                                                                                  
659  perm_inter_right l₂ p₂ ▸ perm_inter_left t₁ p₁
id   └──────────────┘ └┘ └┘  └─────────────┘ └┘ └┘
src  └──────────────┘        └─────────────┘
typ  └──────────────┘ └┘ └┘  └─────────────┘ └┘ └┘
660  end
661  
662  theorem perm_pairwise {R : α → α → Prop} (S : symmetric R) :
id                                               └───────┘ 
src                                                └───────┘
typ                                              └───────┘ 
663    ∀ {l₁ l₂ : list α} (p : l₁ ~ l₂), pairwise R l₁ ↔ pairwise R l₂ :=
id                └──┘        └┘  └┘   └──────┘  └┘  └──────┘  └┘
src               └──┘                  └──────┘       └──────┘
typ               └──┘        └┘  └┘   └──────┘  └┘  └──────┘  └┘
doc                                     └──────┘        └──────┘
664  suffices ∀ {l₁ l₂}, l₁ ~ l₂ → pairwise R l₁ → pairwise R l₂, from λ l₁ l₂ p, ⟨this p, this p.symm⟩,
id               └┘ └┘   └┘  └┘   └──────┘  └┘   └──────┘  └┘         └┘ └┘    └──┘   └──┘ └───┘
src                               └──────┘        └──────┘                                      └───┘
typ              └┘ └┘   └┘  └┘   └──────┘  └┘   └──────┘  └┘         └┘ └┘    └──┘   └──┘ └───┘
doc                               └──────┘        └──────┘
665  λ l₁ l₂ p d, begin
id     └┘ └┘  
typ    └┘ └┘  
st                └─────
666    induction d with a l₁ h d IH generalizing l₂,
id               
src    └────────┘ └───────────────────────────────┘
typ    └────────┘└───────────────────────────────┘
doc    └────────┘ └───────────────────────────────┘
txt    └────────┘ └───────────────────────────────┘
par    └────────┘ └───────────────────────────────┘
pid              └──────────────┘└──────────────┘
st   ─────────────────────────────────────────────┘└─
667    { rw eq_nil_of_perm_nil p, constructor },
id          └────────────────┘ 
src      └─┘└────────────────┘   └──────────┘
typ      └─┘└────────────────┘  └──────────┘
doc      └─┘                     └──────────┘
txt      └─┘                     └──────────┘
par      └─┘                     └──────────┘
pid                                        
st   ───┘└─────────────────────┘└────────────┘└┘
668    { have : a ∈ l₂ := perm_subset p (mem_cons_self _ _),
id                └┘    └─────────┘   └───────────┘
src      └─────┘   └──┘└─────────┘  └───────────┘└───┘
typ      └─────┘└┘└──┘└─────────┘ └───────────┘└───┘
doc      └─────┘    └──┘                          └───┘
txt      └─────┘    └──┘                          └───┘
par      └─────┘    └──┘                          └───┘
pid      └───┘└┘    └──┘                          └───┘
st   ─────────────────────────────────────────────────────┘└─
669      rcases mem_split this with ⟨s₂, t₂, rfl⟩,
id              └───────┘ └──┘
src      └─────┘└───────┘    └─────────────────┘
typ      └─────┘└───────┘└──┘└─────────────────┘
doc      └─────┘             └─────────────────┘
txt      └─────┘             └─────────────────┘
par      └─────┘             └─────────────────┘
pid                         └─────────────────┘
st   ───────────────────────────────────────────┘└─
670      have p' := perm_cons_inv (p.trans perm_middle),
id                  └───────────┘  └─────┘ └─────────┘
src      └─────────┘└───────────┘ └─────┘└─────────┘
typ      └─────────┘└───────────┘ └─────┘└─────────┘
doc      └─────────┘                                
txt      └─────────┘                                
par      └─────────┘                                
pid      └─────┘└─┘                                
st   ─────────────────────────────────────────────────┘└─
671      refine (pairwise_middle S).2 (pairwise_cons.2 ⟨λ b m, _, IH _ p'⟩),
id               └─────────────┘      └───────────┘              └┘   └┘
src      └─────┘ └─────────────┘ └──┘ └───────────┘└─┘  └───────┘  └─┘  └┘
typ      └─────┘ └─────────────┘└──┘ └───────────┘└─┘  └───────┘└┘└─┘└┘└┘
doc      └─────┘                 └──┘              └─┘  └───────┘  └─┘  └┘
txt      └─────┘                 └──┘              └─┘  └───────┘  └─┘  └┘
par      └─────┘                 └──┘              └─┘  └───────┘  └─┘  └┘
pid                             └──┘              └─┘  └───────┘  └─┘  └┘
st   ─────────────────────────────────────────────────────────────────────┘└─
672      exact h _ (perm_subset p'.symm m) }
id                 └─────────┘ └─────┘ 
src      └────┘ └─┘ └─────────┘└─────┘ └┘
typ      └────┘└─┘ └─────────┘└─────┘└┘
doc      └────┘ └─┘                    └┘
txt      └────┘ └─┘                    └┘
par      └────┘ └─┘                    └┘
pid            └─┘                    
st   ─────────────────────────────────────┘└─
673  end
st   ──┘
674  
675  theorem perm_nodup {l₁ l₂ : list α} : l₁ ~ l₂ → (nodup l₁ ↔ nodup l₂) :=
id                               └──┘     └┘  └┘    └───┘ └┘  └───┘ └┘
src                              └──┘                └───┘     └───┘
typ                              └──┘     └┘  └┘    └───┘ └┘  └───┘ └┘
doc                                                  └───┘      └───┘
676  perm_pairwise $ @ne.symm α
id   └───────────┘    └─────┘ 
src  └───────────┘    └─────┘
typ  └───────────┘    └─────┘ 
677  
678  theorem perm_bind_left {l₁ l₂ : list α} (f : α → list β) (p : l₁ ~ l₂) :
id                                   └──┘           └──┘        └┘  └┘
src                                  └──┘             └──┘            
typ                                  └──┘           └──┘        └┘  └┘
doc                                                                   
679    l₁.bind f ~ l₂.bind f :=
id     └┘└───┘   └┘└───┘ 
src      └───┘      └───┘
typ    └┘└───┘   └┘└───┘ 
doc              
680  begin
st   └─────
681    induction p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂, {simp},
id               
src    └────────┘ └─────────────────────────────────────────────┘   └──┘
typ    └────────┘└─────────────────────────────────────────────┘   └──┘
doc    └────────┘ └─────────────────────────────────────────────┘   └──┘
txt    └────────┘ └─────────────────────────────────────────────┘   └──┘
par    └────────┘ └─────────────────────────────────────────────┘   └──┘
pid              └────────────────────────────────────────────┘
st   ───────────────────────────────────────────────────────────┘└─────┘└┘
682    { simp, exact perm_app_right _ IH },
id                   └────────────┘   └┘
src      └──┘  └────┘└────────────┘└─┘  
typ      └──┘  └────┘└────────────┘└─┘└┘
doc      └──┘  └────┘              └─┘  
txt      └──┘  └────┘              └─┘  
par      └──┘  └────┘              └─┘  
pid                               └─┘  
st   ───┘└──┘└──────────────────────────┘└┘
683    { simp, rw [← append_assoc, ← append_assoc], exact perm_app_left _ perm_app_comm },
id                   └──────────┘    └──────────┘         └───────────┘   └───────────┘
src      └──┘  └────┘└──────────┘└──┘└──────────┘  └────┘└───────────┘└─┘└───────────┘
typ      └──┘  └────┘└──────────┘└──┘└──────────┘  └────┘└───────────┘└─┘└───────────┘
doc      └──┘  └────┘            └──┘              └────┘             └─┘             
txt      └──┘  └────┘            └──┘              └────┘             └─┘             
par      └──┘  └────┘            └──┘              └────┘             └─┘             
pid              └──┘            └──┘                                └─┘             
st   ───┘└──┘└──────────────────┘└──────────────┘└────────────────────────────────────┘└┘
684    { exact trans IH₁ IH₂ }
id             └───┘ └─┘ └─┘
src      └────┘└───┘      
typ      └────┘└───┘└─┘└─┘
doc      └────┘           
txt      └────┘           
par      └────┘           
pid                      
st   ───────────────────────┘└─
685  end
st   ──┘
686  
687  theorem perm_bind_right (l : list α) {f g : α → list β} (h : ∀ a, f a ~ g a) :
id                                └──┘             └──┘                
src                               └──┘               └──┘                  
typ                               └──┘             └──┘                
doc                                                                        
688    l.bind f ~ l.bind g :=
id     └───┘   └───┘ 
src     └───┘     └───┘
typ    └───┘   └───┘ 
doc             
689  by induction l with a l IH; simp; exact perm_app (h a) IH
id                                          └──────┘     └┘
src     └────────┘ └──────────┘  └──┘  └────┘└──────┘   └┘  
typ     └────────┘└──────────┘  └──┘  └────┘└──────┘ └┘└┘
doc     └────────┘ └──────────┘  └──┘  └────┘           └┘  
txt     └────────┘ └──────────┘  └──┘  └────┘           └┘  
par     └────────┘ └──────────┘  └──┘  └────┘           └┘  
pid               └─────────┘                        └┘  
st     └───────────────────────────────────────────────────────
690  
src  
typ  
doc  
txt  
par  
pid  
st   
691  theorem perm_product_left {l₁ l₂ : list α} (t₁ : list β) (p : l₁ ~ l₂) : product l₁ t₁ ~ product l₂ t₁ :=
id                                      └──┘         └──┘        └┘  └┘    └─────┘ └┘ └┘  └─────┘ └┘ └┘
src                                     └──┘          └──┘                   └─────┘        └─────┘
typ                                     └──┘         └──┘        └┘  └┘    └─────┘ └┘ └┘  └─────┘ └┘ └┘
doc                                                                          └─────┘        └─────┘
692  perm_bind_left _ p
id   └────────────┘   
src  └────────────┘
typ  └────────────┘   
693  
694  theorem perm_product_right (l : list α) {t₁ t₂ : list β} (p : t₁ ~ t₂) : product l t₁ ~ product l t₂ :=
id                                   └──┘            └──┘        └┘  └┘    └─────┘  └┘  └─────┘  └┘
src                                  └──┘             └──┘                   └─────┘       └─────┘
typ                                  └──┘            └──┘        └┘  └┘    └─────┘  └┘  └─────┘  └┘
doc                                                                          └─────┘       └─────┘
695  perm_bind_right _ $ λ a, perm_map _ p
id   └─────────────┘         └──────┘   
src  └─────────────┘          └──────┘
typ  └─────────────┘         └──────┘   
696  
697  @[congr] theorem perm_product {l₁ l₂ : list α} {t₁ t₂ : list β}
id                                          └──┘            └──┘ 
src    └───┘                                └──┘             └──┘
typ                                         └──┘            └──┘ 
doc    └───┘
698    (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : product l₁ t₁ ~ product l₂ t₂ :=
id           └┘  └┘        └┘  └┘    └─────┘ └┘ └┘  └─────┘ └┘ └┘
src                                  └─────┘        └─────┘
typ          └┘  └┘        └┘  └┘    └─────┘ └┘ └┘  └─────┘ └┘ └┘
doc                                  └─────┘        └─────┘
699  trans (perm_product_left t₁ p₁) (perm_product_right l₂ p₂)
id   └───┘  └───────────────┘ └┘ └┘   └────────────────┘ └┘ └┘
src  └───┘  └───────────────┘         └────────────────┘
typ  └───┘  └───────────────┘ └┘ └┘   └────────────────┘ └┘ └┘
700  
701  theorem sublists_cons_perm_append (a : α) (l : list α) :
id                                                 └──┘ 
src                                                 └──┘
typ                                                └──┘ 
702    sublists (a :: l) ~ sublists l ++ map (cons a) (sublists l) :=
id     └──────┘   └┘    └──────┘  └┘ └─┘  └──┘    └──────┘ 
src    └──────┘    └┘     └──────┘   └┘ └─┘  └──┘     └──────┘
typ    └──────┘   └┘    └──────┘  └┘ └─┘  └──┘    └──────┘ 
doc    └──────┘           └──────┘                    └──────┘
703  begin
st   └─────
704    simp [sublists, sublists_aux_cons_cons],
id           └──────┘  └────────────────────┘
src    └────┘└──────┘└┘└────────────────────┘
typ    └────┘└──────┘└┘└────────────────────┘
doc    └────┘└──────┘└┘                      
txt    └────┘        └┘                      
par    └────┘        └┘                      
pid                └┘                      
st   ────────────────────────────────────────┘└─
705    refine skip _ ((skip _ _).trans perm_middle.symm),
id                     └──┘            └──────────────┘
src    └─────┘    └─┘  └──┘└──────────┘└──────────────┘
typ    └─────┘    └─┘  └──┘└──────────┘└──────────────┘
doc    └─────┘    └─┘      └──────────┘                
txt    └─────┘    └─┘      └──────────┘                
par    └─────┘    └─┘      └──────────┘                
pid              └─┘      └──────────┘                
st   ──────────────────────────────────────────────────┘└─
706    induction sublists_aux l cons with b l IH; simp,
id               └──────────┘  └──┘
src    └────────┘└──────────┘ └──┘└──────────┘  └──┘
typ    └────────┘└──────────┘└──┘└──────────┘  └──┘
doc    └────────┘                 └──────────┘  └──┘
txt    └────────┘                 └──────────┘  └──┘
par    └────────┘                 └──────────┘  └──┘
pid                              └─────────┘
st   ────────────────────────────────────────────────┘└─
707    exact skip b ((skip _ IH).trans perm_middle.symm)
id                   └──┘   └┘        └──────────────┘
src    └────┘       └──┘└─┘  └──────┘└──────────────┘└┘
typ    └────┘      └──┘└─┘└┘└──────┘└──────────────┘└┘
doc    └────┘           └─┘  └──────┘                └┘
txt    └────┘           └─┘  └──────┘                └┘
par    └────┘           └─┘  └──────┘                └┘
pid                    └─┘  └──────┘                
st   ───────────────────────────────────────────────────┘
708  end
st   └─┘
709  
710  theorem sublists_perm_sublists' : ∀ l : list α, sublists l ~ sublists' l
id                                          └──┘   └──────┘   └───────┘ 
src                                          └──┘    └──────┘    └───────┘
typ                                         └──┘   └──────┘   └───────┘ 
doc                                                  └──────┘    └───────┘
711  | []     := perm.refl _
id     └┘        └───────┘
src    └┘        └───────┘
typ    └┘        └───────┘
712  | (a::l) := let IH := sublists_perm_sublists' l in
id       └┘         └┘    └─────────────────────┘
src      └┘
typ      └┘         └┘    └─────────────────────┘
713    by rw sublists'_cons; exact
id           └────────────┘
src       └─┘└────────────┘  └─────
typ       └─┘└────────────┘  └─────
doc       └─┘                └─────
txt       └─┘                └─────
par       └─┘                └─────
pid                              
st       └─────────────────────────
714    (sublists_cons_perm_append _ _).trans (perm_app IH (perm_map _ IH))
id      └───────────────────────┘             └──────┘     └──────┘   └┘
src  ─┘ └───────────────────────┘└──────────┘ └──────┘   └──────┘└─┘  └──
typ  ─┘ └───────────────────────┘└──────────┘ └──────┘   └──────┘└─┘└┘└──
doc  ─┘                          └──────────┘                    └─┘  └──
txt  ─┘                          └──────────┘                    └─┘  └──
par  ─┘                          └──────────┘                    └─┘  └──
pid  ─┘                          └──────────┘                    └─┘  └┘
st   ──────────────────────────────────────────────────────────────────────
715  
src  
typ  
doc  
txt  
par  
pid  
st   
716  theorem revzip_sublists (l : list α) :
id                                └──┘ 
src                               └──┘
typ                               └──┘ 
717    ∀ l₁ l₂, (l₁, l₂) ∈ revzip l.sublists → l₁ ++ l₂ ~ l :=
id       └┘ └┘  └┘  └┘   └────┘ └───────┘   └┘ └┘ └┘  
src                      └────┘  └───────┘      └┘    
typ      └┘ └┘  └┘  └┘   └────┘ └───────┘   └┘ └┘ └┘  
doc                                └───────┘            
718  begin
st   └─────
719    rw revzip,
id        └────┘
src    └─┘└────┘
typ    └─┘└────┘
doc    └─┘
txt    └─┘
par    └─┘
pid      
st   ──────────┘└─
720    apply list.reverse_rec_on l,
id           └─────────────────┘ 
src    └────┘└─────────────────┘
typ    └────┘└─────────────────┘
doc    └────┘                   
txt    └────┘                   
par    └────┘                   
pid                            
st   ────────────────────────────┘└─
721    { intros l₁ l₂ h, simp at h, simp [h] },
id                                        
src      └────────────┘  └───────┘  └────┘ └┘
typ      └────────────┘  └───────┘  └────┘└┘
doc      └────────────┘  └───────┘  └────┘ └┘
txt      └────────────┘  └───────┘  └────┘ └┘
par      └────────────┘  └───────┘  └────┘ └┘
pid            └──────┘      └──┘       
st   ───┘└────────────┘└─────────┘└─────────┘└┘
722    { intros l a IH l₁ l₂ h,
src      └───────────────────┘
typ      └───────────────────┘
doc      └───────────────────┘
txt      └───────────────────┘
par      └───────────────────┘
pid            └─────────────┘
st   ────────────────────────┘└─
723      rw [sublists_concat, reverse_append, zip_append, ← map_reverse,
id           └─────────────┘  └────────────┘  └────────┘    └─────────┘
src      └──┘└─────────────┘└┘└────────────┘└┘└────────┘└──┘└─────────┘└─
typ      └──┘└─────────────┘└┘└────────────┘└┘└────────┘└──┘└─────────┘└─
doc      └──┘               └┘              └┘          └──┘           └─
txt      └──┘               └┘              └┘          └──┘           └─
par      └──┘               └┘              └┘          └──┘           └─
pid        └┘               └┘              └┘          └──┘           └─
st   ──────────────────────┘└──────────────┘└──────────┘└─────────────┘└─
724          zip_map_right, zip_map_left] at h; [simp at h, simp],
id           └───────────┘  └──────────┘        
src  ───────┘└───────────┘└┘└──────────┘└────┘  └───────┘  └──┘
typ  ───────┘└───────────┘└┘└──────────┘└────┘  └───────┘  └──┘
doc  ───────┘             └┘            └────┘   └───────┘  └──┘
txt  ───────┘             └┘            └────┘   └───────┘  └──┘
par  ───────┘             └┘            └────┘   └───────┘  └──┘
pid  ───────┘             └┘            └───┘       └──┘
st   ────────────────────┘└────────────┘└──────────────────────┘└─
725      rcases h with ⟨l₁, l₂', h, rfl, rfl⟩ | ⟨l₁', l₂, h, rfl, rfl⟩,
id              
src      └─────┘ └───────────────────────────────────────────────────┘
typ      └─────┘└───────────────────────────────────────────────────┘
doc      └─────┘ └───────────────────────────────────────────────────┘
txt      └─────┘ └───────────────────────────────────────────────────┘
par      └─────┘ └───────────────────────────────────────────────────┘
pid             └───────────────────────────────────────────────────┘
st   ────────────────────────────────────────────────────────────────┘└─
726      { rw ← append_assoc,
id              └──────────┘
src        └───┘└──────────┘
typ        └───┘└──────────┘
doc        └───┘
txt        └───┘
par        └───┘
pid          └─┘
st   ─────┘└───────────────┘└─
727        exact perm_app_left _ (IH _ _ h) },
id               └───────────┘    └┘     
src        └────┘└───────────┘└─┘   └───┘ └┘
typ        └────┘└───────────┘└─┘ └┘└───┘└┘
doc        └────┘             └─┘   └───┘ └┘
txt        └────┘             └─┘   └───┘ └┘
par        └────┘             └─┘   └───┘ └┘
pid                          └─┘   └───┘ 
st   ──────────────────────────────────────┘└┘
728      { rw append_assoc,
id            └──────────┘
src        └─┘└──────────┘
typ        └─┘└──────────┘
doc        └─┘
txt        └─┘
par        └─┘
pid          
st   ────────────────────┘└─
729        apply (perm_app_right _ perm_app_comm).trans,
id                └────────────┘   └───────────┘
src        └────┘ └────────────┘└─┘└───────────┘└─────┘
typ        └────┘ └────────────┘└─┘└───────────┘└─────┘
doc        └────┘               └─┘             └─────┘
txt        └────┘               └─┘             └─────┘
par        └────┘               └─┘             └─────┘
pid                            └─┘             └────┘
st   ─────────────────────────────────────────────────┘└─
730        rw ← append_assoc,
id              └──────────┘
src        └───┘└──────────┘
typ        └───┘└──────────┘
doc        └───┘
txt        └───┘
par        └───┘
pid          └─┘
st   ──────────────────────┘└─
731        exact perm_app_left _ (IH _ _ h) } }
id               └───────────┘    └┘     
src        └────┘└───────────┘└─┘   └───┘ └┘
typ        └────┘└───────────┘└─┘ └┘└───┘└┘
doc        └────┘             └─┘   └───┘ └┘
txt        └────┘             └─┘   └───┘ └┘
par        └────┘             └─┘   └───┘ └┘
pid                          └─┘   └───┘ 
st   ──────────────────────────────────────┘└───
732  end
st   ──┘
733  
734  theorem revzip_sublists' (l : list α) :
id                                 └──┘ 
src                                └──┘
typ                                └──┘ 
735    ∀ l₁ l₂, (l₁, l₂) ∈ revzip l.sublists' → l₁ ++ l₂ ~ l :=
id       └┘ └┘  └┘  └┘   └────┘ └────────┘   └┘ └┘ └┘  
src                      └────┘  └────────┘      └┘    
typ      └┘ └┘  └┘  └┘   └────┘ └────────┘   └┘ └┘ └┘  
doc                                └────────┘            
736  begin
st   └─────
737    rw revzip,
id        └────┘
src    └─┘└────┘
typ    └─┘└────┘
doc    └─┘
txt    └─┘
par    └─┘
pid      
st   ──────────┘└─
738    induction l with a l IH; intros l₁ l₂ h,
id               
src    └────────┘ └──────────┘  └────────────┘
typ    └────────┘└──────────┘  └────────────┘
doc    └────────┘ └──────────┘  └────────────┘
txt    └────────┘ └──────────┘  └────────────┘
par    └────────┘ └──────────┘  └────────────┘
pid              └─────────┘        └──────┘
st   ────────────────────────────────────────┘└─
739    { simp at h, simp [h] },
id                        
src      └───────┘  └────┘ └┘
typ      └───────┘  └────┘└┘
doc      └───────┘  └────┘ └┘
txt      └───────┘  └────┘ └┘
par      └───────┘  └────┘ └┘
pid          └──┘       
st   ───┘└───────┘└─────────┘└┘
740    { rw [sublists'_cons, reverse_append, zip_append, ← map_reverse,
id           └────────────┘  └────────────┘  └────────┘    └─────────┘
src      └──┘└────────────┘└┘└────────────┘└┘└────────┘└──┘└─────────┘└─
typ      └──┘└────────────┘└┘└────────────┘└┘└────────┘└──┘└─────────┘└─
doc      └──┘              └┘              └┘          └──┘           └─
txt      └──┘              └┘              └┘          └──┘           └─
par      └──┘              └┘              └┘          └──┘           └─
pid        └┘              └┘              └┘          └──┘           └─
st   ─────────────────────┘└──────────────┘└──────────┘└─────────────┘└─
741          zip_map_right, zip_map_left] at h; [simp at h, simp],
id           └───────────┘  └──────────┘        
src  ───────┘└───────────┘└┘└──────────┘└────┘  └───────┘  └──┘
typ  ───────┘└───────────┘└┘└──────────┘└────┘  └───────┘  └──┘
doc  ───────┘             └┘            └────┘   └───────┘  └──┘
txt  ───────┘             └┘            └────┘   └───────┘  └──┘
par  ───────┘             └┘            └────┘   └───────┘  └──┘
pid  ───────┘             └┘            └───┘       └──┘
st   ────────────────────┘└────────────┘└──────────────────────┘└─
742      rcases h with ⟨l₁, l₂', h, rfl, rfl⟩ | ⟨l₁', l₂, h, rfl, rfl⟩,
id              
src      └─────┘ └───────────────────────────────────────────────────┘
typ      └─────┘└───────────────────────────────────────────────────┘
doc      └─────┘ └───────────────────────────────────────────────────┘
txt      └─────┘ └───────────────────────────────────────────────────┘
par      └─────┘ └───────────────────────────────────────────────────┘
pid             └───────────────────────────────────────────────────┘
st   ────────────────────────────────────────────────────────────────┘└─
743      { exact perm_middle.trans (skip _ (IH _ _ h)) },
id               └───────────────┘  └──┘    └┘     
src        └────┘└───────────────┘ └──┘└─┘   └───┘ └─┘
typ        └────┘└───────────────┘ └──┘└─┘ └┘└───┘└─┘
doc        └────┘                      └─┘   └───┘ └─┘
txt        └────┘                      └─┘   └───┘ └─┘
par        └────┘                      └─┘   └───┘ └─┘
pid                                   └─┘   └───┘ └┘
st   ─────┘└──────────────────────────────────────────┘└┘
744      { exact skip _ (IH _ _ h) } }
id               └──┘    └┘     
src        └────┘└──┘└─┘   └───┘ └┘
typ        └────┘└──┘└─┘ └┘└───┘└┘
doc        └────┘    └─┘   └───┘ └┘
txt        └────┘    └─┘   └───┘ └┘
par        └────┘    └─┘   └───┘ └┘
pid                 └─┘   └───┘ 
st   ─────────────────────────────┘└───
745  end
st   ──┘
746  
747  theorem perm_lookmap (f : α → option α) {l₁ l₂ : list α}
id                                └────┘            └──┘ 
src                                └────┘             └──┘
typ                               └────┘            └──┘ 
748    (H : pairwise (λ a b, ∀ (c ∈ f a) (d ∈ f b), a = b ∧ c = d) l₁)
id          └──────┘                               └┘
src         └──────┘                                       
typ         └──────┘                               └┘
doc         └──────┘
749    (p : l₁ ~ l₂) : lookmap f l₁ ~ lookmap f l₂ :=
id          └┘  └┘    └─────┘  └┘  └─────┘  └┘
src                   └─────┘       └─────┘
typ         └┘  └┘    └─────┘  └┘  └─────┘  └┘
doc                   └─────┘       └─────┘
750  begin
st   └─────
751    let F := λ a b, ∀ (c ∈ f a) (d ∈ f b), a = b ∧ c = d,
id                                             
src    └───────┘ └────┘ └────┘  └─────┘        
typ    └───────┘ └────┘ └────┘  └─────┘       
doc    └───────┘ └────┘ └────┘  └─────┘         
txt    └───────┘ └────┘ └────┘  └─────┘         
par    └───────┘ └────┘ └────┘  └─────┘         
pid    └───┘└─┘ └────┘ └────┘  └─────┘         
st   ─────────────────────────────────────────────────────┘└─
752    change pairwise F l₁ at H,
id            └──────┘  └┘
src    └─────┘└──────┘   └───┘
typ    └─────┘└──────┘└┘└───┘
doc    └─────┘└──────┘   └───┘
txt    └─────┘           └───┘
par    └─────┘           └───┘
pid                     └──┘
st   ──────────────────────────┘└─
753    induction p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂, {simp},
id               
src    └────────┘ └─────────────────────────────────────────────┘   └──┘
typ    └────────┘└─────────────────────────────────────────────┘   └──┘
doc    └────────┘ └─────────────────────────────────────────────┘   └──┘
txt    └────────┘ └─────────────────────────────────────────────┘   └──┘
par    └────────┘ └─────────────────────────────────────────────┘   └──┘
pid              └────────────────────────────────────────────┘
st   ───────────────────────────────────────────────────────────┘└─────┘└┘
754    { cases h : f a,
id                  
src      └────┘ └─┘ 
typ      └────┘ └─┘
doc      └────┘ └─┘ 
txt      └────┘ └─┘ 
par      └────┘ └─┘ 
pid            └─┘ 
st   ───┘└───────────┘└─
755      { simp [h], exact (IH (pairwise_cons.1 H).2).skip _ },
id                         └┘  └───────────┘   
src        └────┘   └────┘    └───────────┘└─┘ └──────────┘
typ        └────┘  └────┘ └┘ └───────────┘└─┘└──────────┘
doc        └────┘   └────┘                 └─┘ └──────────┘
txt        └────┘   └────┘                 └─┘ └──────────┘
par        └────┘   └────┘                 └─┘ └──────────┘
pid                                     └─┘ └─────────┘
st   ─────┘└──────┘└────────────────────────────────────────┘└┘
756      { simp [lookmap_cons_some _ _ h], exact p.skip _ } },
id               └───────────────┘              └────┘
src        └────┘└───────────────┘└───┘   └────┘└────┘└─┘
typ        └────┘└───────────────┘└───┘  └────┘└────┘└─┘
doc        └────┘                 └───┘   └────┘      └─┘
txt        └────┘                 └───┘   └────┘      └─┘
par        └────┘                 └───┘   └────┘      └─┘
pid                             └───┘              └┘
st   ───────────────────────────────────┘└───────────────┘└──┘
757    { cases h₁ : f a with c; cases h₂ : f b with d,
id                                        
src      └────┘  └─┘  └─────┘  └────┘  └─┘  └─────┘
typ      └────┘  └─┘└─────┘  └────┘  └─┘└─────┘
doc      └────┘  └─┘  └─────┘  └────┘  └─┘  └─────┘
txt      └────┘  └─┘  └─────┘  └────┘  └─┘  └─────┘
par      └────┘  └─┘  └─────┘  └────┘  └─┘  └─────┘
pid             └─┘  └─────┘         └─┘  └─────┘
st   ───┘└──────────────────────────────────────────┘└─
758      { simp [h₁, h₂], apply swap },
id               └┘  └┘         └──┘
src        └────┘  └┘    └────┘└──┘
typ        └────┘└┘└┘└┘  └────┘└──┘
doc        └────┘  └┘    └────┘    
txt        └────┘  └┘    └────┘    
par        └────┘  └┘    └────┘    
pid              └┘             
st   ─────┘└───────────┘└───────────┘└┘
759      { simp [h₁, lookmap_cons_some _ _ h₂], apply swap },
id               └┘  └───────────────┘     └┘         └──┘
src        └────┘  └┘└───────────────┘└───┘    └────┘└──┘
typ        └────┘└┘└┘└───────────────┘└───┘└┘  └────┘└──┘
doc        └────┘  └┘                 └───┘    └────┘    
txt        └────┘  └┘                 └───┘    └────┘    
par        └────┘  └┘                 └───┘    └────┘    
pid              └┘                 └───┘             
st   ─────┘└─────────────────────────────────┘└───────────┘└┘
760      { simp [lookmap_cons_some _ _ h₁, h₂], apply swap },
id               └───────────────┘     └┘  └┘         └──┘
src        └────┘└───────────────┘└───┘  └┘    └────┘└──┘
typ        └────┘└───────────────┘└───┘└┘└┘└┘  └────┘└──┘
doc        └────┘                 └───┘  └┘    └────┘    
txt        └────┘                 └───┘  └┘    └────┘    
par        └────┘                 └───┘  └┘    └────┘    
pid                             └───┘  └┘             
st   ─────┘└─────────────────────────────────┘└───────────┘└┘
761      { simp [lookmap_cons_some _ _ h₁, lookmap_cons_some _ _ h₂],
id               └───────────────┘     └┘  └───────────────┘     └┘
src        └────┘└───────────────┘└───┘  └┘└───────────────┘└───┘  
typ        └────┘└───────────────┘└───┘└┘└┘└───────────────┘└───┘└┘
doc        └────┘                 └───┘  └┘                 └───┘  
txt        └────┘                 └───┘  └┘                 └───┘  
par        └────┘                 └───┘  └┘                 └───┘  
pid                             └───┘  └┘                 └───┘  
st   ──────────────────────────────────────────────────────────────┘└─
762        rcases (pairwise_cons.1 H).1 _ (or.inl rfl) _ h₂ _ h₁ with ⟨rfl, rfl⟩,
id                 └───────────┘          └────┘ └─┘    └┘   └┘
src        └─────┘ └───────────┘└─┘ └────┘ └────┘└─┘└──┘  └─┘  └──────────────┘
typ        └─────┘ └───────────┘└─┘└────┘ └────┘└─┘└──┘└┘└─┘└┘└──────────────┘
doc        └─────┘              └─┘ └────┘          └──┘  └─┘  └──────────────┘
txt        └─────┘              └─┘ └────┘          └──┘  └─┘  └──────────────┘
par        └─────┘              └─┘ └────┘          └──┘  └─┘  └──────────────┘
pid                            └─┘ └────┘          └──┘  └─┘  └──────────────┘
st   ──────────────────────────────────────────────────────────────────────────┘└─
763        refl } },
src        └───┘
typ        └───┘
doc        └───┘
txt        └───┘
par        └───┘
pid            
st   ──────────┘└──┘
764    { refine (IH₁ H).trans (IH₂ ((perm_pairwise _ p₁).1 H)),
id               └─┘           └─┘   └───────────┘   └┘    
src      └─────┘     └──────┘      └───────────┘└─┘  └──┘ └┘
typ      └─────┘ └─┘ └──────┘ └─┘  └───────────┘└─┘└┘└──┘└┘
doc      └─────┘     └──────┘                   └─┘  └──┘ └┘
txt      └─────┘     └──────┘                   └─┘  └──┘ └┘
par      └─────┘     └──────┘                   └─┘  └──┘ └┘
pid                 └──────┘                   └─┘  └──┘ └┘
st   ────────────────────────────────────────────────────────┘└─
765      exact λ a b h c h₁ d h₂, (h d h₂ c h₁).imp eq.symm eq.symm }
id                                                          └─────┘
src      └────┘ └────────────────┘        └────┘       └─────┘
typ      └────┘ └────────────────┘        └────┘       └─────┘
doc      └────┘ └────────────────┘        └────┘              
txt      └────┘ └────────────────┘        └────┘              
par      └────┘ └────────────────┘        └────┘              
pid            └────────────────┘        └────┘              
st   ──────────────────────────────────────────────────────────────┘└─
766  end
st   ──┘
767  
768  theorem perm_erasep (f : α → Prop) [decidable_pred f] {l₁ l₂ : list α}
id                                      └────────────┘            └──┘ 
src                                      └────────────┘             └──┘
typ                                     └────────────┘            └──┘ 
769    (H : pairwise (λ a b, f a → f b → false) l₁)
id          └──────┘               └───┘  └┘
src         └──────┘                     └───┘
typ         └──────┘               └───┘  └┘
doc         └──────┘
770    (p : l₁ ~ l₂) : erasep f l₁ ~ erasep f l₂ :=
id          └┘  └┘    └────┘  └┘  └────┘  └┘
src                   └────┘       └────┘
typ         └┘  └┘    └────┘  └┘  └────┘  └┘
doc                               
771  begin
st   └─────
772    let F := λ a b, f a → f b → false,
id                                └───┘
src    └───────┘ └────┘      └───┘
typ    └───────┘ └────┘     └───┘
doc    └───────┘ └────┘      
txt    └───────┘ └────┘      
par    └───────┘ └────┘      
pid    └───┘└─┘ └────┘      
st   ──────────────────────────────────┘└─
773    change pairwise F l₁ at H,
id            └──────┘  └┘
src    └─────┘└──────┘   └───┘
typ    └─────┘└──────┘└┘└───┘
doc    └─────┘└──────┘   └───┘
txt    └─────┘           └───┘
par    └─────┘           └───┘
pid                     └──┘
st   ──────────────────────────┘└─
774    induction p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂, {simp},
id               
src    └────────┘ └─────────────────────────────────────────────┘   └──┘
typ    └────────┘└─────────────────────────────────────────────┘   └──┘
doc    └────────┘ └─────────────────────────────────────────────┘   └──┘
txt    └────────┘ └─────────────────────────────────────────────┘   └──┘
par    └────────┘ └─────────────────────────────────────────────┘   └──┘
pid              └────────────────────────────────────────────┘
st   ───────────────────────────────────────────────────────────┘└─────┘└┘
775    { by_cases h : f a,
id                     
src      └───────┘ └─┘ 
typ      └───────┘ └─┘
doc      └───────┘ └─┘ 
txt      └───────┘ └─┘ 
par      └───────┘ └─┘ 
pid               └─┘ 
st   ───┘└──────────────┘└─
776      { simp [h, p] },
id                 
src        └────┘ └┘ └┘
typ        └────┘└┘└┘
doc        └────┘ └┘ └┘
txt        └────┘ └┘ └┘
par        └────┘ └┘ └┘
pid             └┘ 
st   ─────┘└──────────┘└┘
777      { simp [h], exact (IH (pairwise_cons.1 H).2).skip _ } },
id                         └┘  └───────────┘   
src        └────┘   └────┘    └───────────┘└─┘ └──────────┘
typ        └────┘  └────┘ └┘ └───────────┘└─┘└──────────┘
doc        └────┘   └────┘                 └─┘ └──────────┘
txt        └────┘   └────┘                 └─┘ └──────────┘
par        └────┘   └────┘                 └─┘ └──────────┘
pid                                     └─┘ └─────────┘
st   ─────────────┘└────────────────────────────────────────┘└──┘
778    { by_cases h₁ : f a; by_cases h₂ : f b; simp [h₁, h₂],
id                                               └┘  └┘
src      └───────┘  └─┘    └───────┘  └─┘    └────┘  └┘  
typ      └───────┘  └─┘  └───────┘  └─┘  └────┘└┘└┘└┘
doc      └───────┘  └─┘    └───────┘  └─┘    └────┘  └┘  
txt      └───────┘  └─┘    └───────┘  └─┘    └────┘  └┘  
par      └───────┘  └─┘    └───────┘  └─┘    └────┘  └┘  
pid                └─┘              └─┘          └┘  
st   ───┘└─────────────────────────────────────────────────┘└─
779      { cases (pairwise_cons.1 H).1 _ (or.inl rfl) h₂ h₁ },
id                └───────────┘          └────┘ └─┘  └┘ └┘
src        └────┘ └───────────┘└─┘ └────┘ └────┘└─┘└┘    
typ        └────┘ └───────────┘└─┘└────┘ └────┘└─┘└┘└┘└┘
doc        └────┘              └─┘ └────┘          └┘    
txt        └────┘              └─┘ └────┘          └┘    
par        └────┘              └─┘ └────┘          └┘    
pid                           └─┘ └────┘          └┘    
st   ─────┘└───────────────────────────────────────────────┘└┘
780      { apply swap } },
id               └──┘
src        └────┘└──┘
typ        └────┘└──┘
doc        └────┘    
txt        └────┘    
par        └────┘    
pid                 
st   ────────────────┘└──┘
781    { refine (IH₁ H).trans (IH₂ ((perm_pairwise _ p₁).1 H)),
id               └─┘           └─┘   └───────────┘   └┘    
src      └─────┘     └──────┘      └───────────┘└─┘  └──┘ └┘
typ      └─────┘ └─┘ └──────┘ └─┘  └───────────┘└─┘└┘└──┘└┘
doc      └─────┘     └──────┘                   └─┘  └──┘ └┘
txt      └─────┘     └──────┘                   └─┘  └──┘ └┘
par      └─────┘     └──────┘                   └─┘  └──┘ └┘
pid                 └──────┘                   └─┘  └──┘ └┘
st   ────────────────────────────────────────────────────────┘└─
782      exact λ a b h h₁ h₂, h h₂ h₁ }
src      └────┘ └────────────┘     
typ      └────┘ └────────────┘     
doc      └────┘ └────────────┘     
txt      └────┘ └────────────┘     
par      └────┘ └────────────┘     
pid            └────────────┘     
st   ────────────────────────────────┘└─
783  end
st   ──┘
784  
785  /- enumerating permutations -/
786  
787  section permutations
788  
789  theorem permutations_aux2_fst (t : α) (ts : list α) (r : list β) : ∀ (ys : list α) (f : list α → β),
id                                              └──┘        └──┘            └──┘        └──┘   
src                                              └──┘         └──┘              └──┘         └──┘
typ                                             └──┘        └──┘            └──┘        └──┘   
790    (permutations_aux2 t ts r ys f).1 = ys ++ ts
id      └───────────────┘  └┘  └┘     └┘ └┘ └┘
src     └───────────────┘                   └┘
typ     └───────────────┘  └┘  └┘     └┘ └┘ └┘
791  | []      f := rfl
id     └┘           └─┘
src    └┘           └─┘
typ    └┘           └─┘
792  | (y::ys) f := match _, permutations_aux2_fst ys _ : ∀ o : list α × list β, o.1 = ys ++ ts →
id      └┘└┘               └───────────────────┘              └──┘   └──┘         └┘ └┘
src      └┘                                                     └──┘    └──┘           └┘
typ     └┘└┘               └───────────────────┘              └──┘   └──┘         └┘ └┘
793        (permutations_aux2._match_1 t y f o).1 = y :: ys ++ ts with
id          └────────────────────────┘            └┘    └┘ └┘
src         └────────────────────────┘              └┘    └┘
typ         └────────────────────────┘            └┘    └┘ └┘
794    | ⟨_, zs⟩, rfl := rfl
id                └─┘    └─┘
src               └─┘    └─┘
typ               └─┘    └─┘
795    end
796  
797  @[simp] theorem permutations_aux2_snd_nil (t : α) (ts : list α) (r : list β) (f : list α → β) :
id                                                          └──┘        └──┘        └──┘    
src                                                          └──┘         └──┘         └──┘
typ                                                         └──┘        └──┘        └──┘    
doc    └──┘
798    (permutations_aux2 t ts r [] f).2 = r := rfl
id      └───────────────┘  └┘  └┘         └─┘
src     └───────────────┘        └┘           └─┘
typ     └───────────────┘  └┘  └┘         └─┘
799  
800  @[simp] theorem permutations_aux2_snd_cons (t : α) (ts : list α) (r : list β) (y : α) (ys : list α) (f : list α → β) :
id                                                           └──┘        └──┘                └──┘        └──┘    
src                                                           └──┘         └──┘                  └──┘         └──┘
typ                                                          └──┘        └──┘                └──┘        └──┘    
doc    └──┘
801    (permutations_aux2 t ts r (y::ys) f).2 = f (t :: y :: ys ++ ts) ::
id      └───────────────┘  └┘   └┘└┘         └┘  └┘ └┘ └┘ └┘  └┘
src     └───────────────┘          └┘              └┘   └┘    └┘     └┘
typ     └───────────────┘  └┘   └┘└┘         └┘  └┘ └┘ └┘ └┘  └┘
802      (permutations_aux2 t ts r ys (λx : list α, f (y::x))).2 :=
id        └───────────────┘  └┘  └┘       └──┘     └┘   
src       └───────────────┘                 └──┘        └┘    
typ       └───────────────┘  └┘  └┘       └──┘     └┘   
803  match _, permutations_aux2_fst t ts r _ _ : ∀ o : list α × list β, o.1 = ys ++ ts →
id            └───────────────────┘  └┘              └──┘   └──┘      └┘ └┘ └┘
src           └───────────────────┘                    └──┘    └──┘           └┘
typ           └───────────────────┘  └┘              └──┘   └──┘      └┘ └┘ └┘
804     (permutations_aux2._match_1 t y f o).2 = f (t :: y :: ys ++ ts) :: o.2 with
id       └────────────────────────┘           └┘  └┘ └┘ └┘ └┘  └┘ 
src      └────────────────────────┘                 └┘   └┘    └┘     └┘  
typ      └────────────────────────┘           └┘  └┘ └┘ └┘ └┘  └┘ 
805  | ⟨_, zs⟩, rfl := rfl
id              └─┘    └─┘
src             └─┘    └─┘
typ             └─┘    └─┘
806  end
807  
808  theorem permutations_aux2_append (t : α) (ts : list α) (r : list β) (ys : list α) (f : list α → β) :
id                                                 └──┘        └──┘         └──┘        └──┘    
src                                                 └──┘         └──┘          └──┘         └──┘
typ                                                └──┘        └──┘         └──┘        └──┘    
809    (permutations_aux2 t ts nil ys f).2 ++ r = (permutations_aux2 t ts r ys f).2 :=
id      └───────────────┘  └┘ └─┘ └┘    └┘    └───────────────┘  └┘  └┘  
src     └───────────────┘      └─┘        └┘     └───────────────┘             
typ     └───────────────┘  └┘ └─┘ └┘    └┘    └───────────────┘  └┘  └┘  
810  by induction ys generalizing f; simp *
id                └┘
src     └────────┘  └─────────────┘  └──────
typ     └────────┘└┘└─────────────┘  └──────
doc     └────────┘  └─────────────┘  └──────
txt     └────────┘  └─────────────┘  └──────
par     └────────┘  └─────────────┘  └──────
pid                └────────────┘      
st     └────────────────────────────────────
811  
src  
typ  
doc  
txt  
par  
pid  
st   
812  theorem mem_permutations_aux2 {t : α} {ts : list α} {ys : list α} {l l' : list α} :
id                                              └──┘         └──┘           └──┘ 
src                                              └──┘          └──┘            └──┘
typ                                             └──┘         └──┘           └──┘ 
813      l' ∈ (permutations_aux2 t ts [] ys (append l)).2 ↔
id       └┘   └───────────────┘  └┘ └┘ └┘  └────┘     
src           └───────────────┘      └┘     └────┘      
typ      └┘   └───────────────┘  └┘ └┘ └┘  └────┘     
814      ∃ l₁ l₂, l₂ ≠ [] ∧ ys = l₁ ++ l₂ ∧ l' = l ++ l₁ ++ t :: l₂ ++ ts :=
id        └┘ └┘ └┘  └┘  └┘  └┘ └┘ └┘  └┘   └┘ └┘ └┘  └┘ └┘ └┘ └┘
src                 └┘         └┘           └┘    └┘   └┘    └┘
typ       └┘ └┘ └┘  └┘  └┘  └┘ └┘ └┘  └┘   └┘ └┘ └┘  └┘ └┘ └┘ └┘
815  begin
st   └─────
816    induction ys with y ys ih generalizing l,
id               └┘
src    └────────┘  └──────────────────────────┘
typ    └────────┘└┘└──────────────────────────┘
doc    └────────┘  └──────────────────────────┘
txt    └────────┘  └──────────────────────────┘
par    └────────┘  └──────────────────────────┘
pid               └──────────┘└─────────────┘
st   ─────────────────────────────────────────┘└─
817    { simp {contextual := tt} },
id                           └┘
src      └───┘ └────────────┘└┘└┘
typ      └───┘ └────────────┘└┘└┘
doc      └───┘ └────────────┘  └┘
txt      └───┘ └────────────┘  └┘
par      └───┘ └────────────┘  └┘
pid           └────────────┘  
st   ───┘└──────────────────────┘└┘
818    { rw [permutations_aux2_snd_cons, show (λ (x : list α), l ++ y :: x) = append (l ++ [y]),
id           └────────────────────────┘               └──┘                  └────┘      
src      └──┘└────────────────────────┘└┘      └────┘└──┘ └─┘       └┘└────┘     └──
typ      └──┘└────────────────────────┘└┘      └────┘└──┘└─┘       └┘└────┘   └──
doc      └──┘                          └┘      └────┘     └─┘       └┘              └──
txt      └──┘                          └┘      └────┘     └─┘       └┘              └──
par      └──┘                          └┘      └────┘     └─┘       └┘              └──
pid        └┘                          └┘      └────┘     └─┘       └┘              └──
st   ─────────────────────────────────┘└─────────────────────────────────────────────────────────
819          by funext; simp, mem_cons_iff, ih], split; intro h,
id                            └──────────┘
src  ──────────┘└────┘└┘└──┘└┘└──────────┘└┘    └───┘  └─────┘
typ  ──────────┘└────┘└┘└──┘└┘└──────────┘└┘└┘  └───┘  └─────┘
doc  ──────────┘└────┘└┘└──┘└┘            └┘    └───┘  └─────┘
txt  ──────────┘└────┘└┘└──┘└┘            └┘    └───┘  └─────┘
par  ──────────┘└────┘└┘└──┘└┘            └┘    └───┘  └─────┘
pid  ────────────────────────┘            └┘                └┘
st   ─────────┘└───────────┘└────────────┘└──┘└──────────────┘└─
820      { rcases h with e | ⟨l₁, l₂, l0, ye, _⟩,
id                
src        └─────┘ └───────────────────────────┘
typ        └─────┘└───────────────────────────┘
doc        └─────┘ └───────────────────────────┘
txt        └─────┘ └───────────────────────────┘
par        └─────┘ └───────────────────────────┘
pid               └───────────────────────────┘
st   ─────┘└───────────────────────────────────┘└─
821        { subst l', exact ⟨[], y::ys, by simp⟩ },
id                 └┘               └┘
src          └────┘    └────┘   └┘     └┘  └──┘└┘
typ          └────┘└┘  └────┘   └┘  └┘└┘  └──┘└┘
doc          └────┘    └────┘   └┘     └┘  └──┘└┘
txt          └────┘    └────┘   └┘     └┘  └──┘└┘
par          └────┘    └────┘   └┘     └┘  └──┘└┘
pid                           └┘     └┘  └────┘
st   ───────┘└──────┘└────────────────────┘└───┘└┘└┘
822        { substs l' ys, exact ⟨y::l₁, l₂, l0, by simp⟩ } },
id                                  └┘  └┘  └┘
src          └──────────┘  └────┘      └┘  └┘  └┘  └──┘└┘
typ          └──────────┘  └────┘   └┘└┘└┘└┘└┘└┘  └──┘└┘
doc          └──────────┘  └────┘      └┘  └┘  └┘  └──┘└┘
txt          └──────────┘  └────┘      └┘  └┘  └┘  └──┘└┘
par          └──────────┘  └────┘      └┘  └┘  └┘  └──┘└┘
pid                └────┘             └┘  └┘  └┘  └────┘
st   ───────────────────┘└────────────────────────┘└───┘└┘└──┘
823      { rcases h with ⟨_ | ⟨y', l₁⟩, l₂, l0, ye, rfl⟩,
id                
src        └─────┘ └───────────────────────────────────┘
typ        └─────┘└───────────────────────────────────┘
doc        └─────┘ └───────────────────────────────────┘
txt        └─────┘ └───────────────────────────────────┘
par        └─────┘ └───────────────────────────────────┘
pid               └───────────────────────────────────┘
st   ──────────────────────────────────────────────────┘└─
824        { simp [ye] },
id                 └┘
src          └────┘  └┘
typ          └────┘└┘└┘
doc          └────┘  └┘
txt          └────┘  └┘
par          └────┘  └┘
pid                
st   ───────┘└────────┘└┘
825        { simp at ye, rcases ye with ⟨rfl, rfl⟩,
id                              └┘
src          └────────┘  └─────┘  └──────────────┘
typ          └────────┘  └─────┘└┘└──────────────┘
doc          └────────┘  └─────┘  └──────────────┘
txt          └────────┘  └─────┘  └──────────────┘
par          └────────┘  └─────┘  └──────────────┘
pid              └───┘          └──────────────┘
st   ─────────────────┘└─────────────────────────┘└─
826          exact or.inr ⟨l₁, l₂, l0, by simp⟩ } } }
id                 └────┘  └┘  └┘  └┘
src          └────┘└────┘   └┘  └┘  └┘  └──┘└┘
typ          └────┘└────┘ └┘└┘└┘└┘└┘└┘  └──┘└┘
doc          └────┘         └┘  └┘  └┘  └──┘└┘
txt          └────┘         └┘  └┘  └┘  └──┘└┘
par          └────┘         └┘  └┘  └┘  └──┘└┘
pid                        └┘  └┘  └┘  └────┘
st   ───────────────────────────────────┘└───┘└┘└─────
827  end
st   ──┘
828  
829  theorem mem_permutations_aux2' {t : α} {ts : list α} {ys : list α} {l : list α} :
id                                               └──┘         └──┘        └──┘ 
src                                               └──┘          └──┘         └──┘
typ                                              └──┘         └──┘        └──┘ 
830      l ∈ (permutations_aux2 t ts [] ys id).2 ↔
id          └───────────────┘  └┘ └┘ └┘ └┘   
src          └───────────────┘      └┘    └┘   
typ         └───────────────┘  └┘ └┘ └┘ └┘   
831      ∃ l₁ l₂, l₂ ≠ [] ∧ ys = l₁ ++ l₂ ∧ l = l₁ ++ t :: l₂ ++ ts :=
id        └┘ └┘ └┘  └┘  └┘  └┘ └┘ └┘    └┘ └┘  └┘ └┘ └┘ └┘
src                 └┘         └┘           └┘   └┘    └┘
typ       └┘ └┘ └┘  └┘  └┘  └┘ └┘ └┘    └┘ └┘  └┘ └┘ └┘ └┘
832  by rw [show @id (list α) = append nil, by funext; refl]; apply mem_permutations_aux2
id                └┘  └──┘    └────┘ └─┘                          └───────────────────┘
src     └──┘     └┘ └──┘ └┘└────┘└─┘└───┘└────┘└┘└──┘  └────┘└───────────────────┘
typ     └──┘     └┘ └──┘└┘└────┘└─┘└───┘└────┘└┘└──┘  └────┘└───────────────────┘
doc     └──┘             └┘          └───┘└────┘└┘└──┘  └────┘                     
txt     └──┘             └┘          └───┘└────┘└┘└──┘  └────┘                     
par     └──┘             └┘          └───┘└────┘└┘└──┘  └────┘                     
pid       └┘             └┘          └────────────────┘                            
st     └─────────────────────────────────────┘└───────────┘└─────────────────────────────
833  
src  
typ  
doc  
txt  
par  
pid  
st   
834  theorem length_permutations_aux2 (t : α) (ts : list α) (ys : list α) (f : list α → β) :
id                                                 └──┘         └──┘        └──┘    
src                                                 └──┘          └──┘         └──┘
typ                                                └──┘         └──┘        └──┘    
835    length (permutations_aux2 t ts [] ys f).2 = length ys :=
id     └────┘  └───────────────┘  └┘ └┘ └┘     └────┘ └┘
src    └────┘  └───────────────┘      └┘         └────┘
typ    └────┘  └───────────────┘  └┘ └┘ └┘     └────┘ └┘
836  by induction ys generalizing f; simp *
id                └┘
src     └────────┘  └─────────────┘  └──────
typ     └────────┘└┘└─────────────┘  └──────
doc     └────────┘  └─────────────┘  └──────
txt     └────────┘  └─────────────┘  └──────
par     └────────┘  └─────────────┘  └──────
pid                └────────────┘      
st     └────────────────────────────────────
837  
src  
typ  
doc  
txt  
par  
pid  
st   
838  theorem foldr_permutations_aux2 (t : α) (ts : list α) (r L : list (list α)) :
id                                                └──┘          └──┘  └──┘ 
src                                                └──┘           └──┘  └──┘
typ                                               └──┘          └──┘  └──┘ 
839    foldr (λy r, (permutations_aux2 t ts r y id).2) r L = L.bind (λ y, (permutations_aux2 t ts [] y id).2) ++ r :=
id     └───┘       └───────────────┘  └┘   └┘       └───┘       └───────────────┘  └┘ └┘  └┘    └┘ 
src    └───┘         └───────────────┘          └┘          └───┘        └───────────────┘      └┘   └┘    └┘
typ    └───┘       └───────────────┘  └┘   └┘       └───┘       └───────────────┘  └┘ └┘  └┘    └┘ 
840  by induction L with l L ih; [refl, {simp [ih], rw ← permutations_aux2_append}]
id                                           └┘        └──────────────────────┘
src     └────────┘ └──────────┘  └──┘   └────┘    └───┘└──────────────────────┘
typ     └────────┘└──────────┘  └──┘   └────┘└┘  └───┘└──────────────────────┘
doc     └────────┘ └──────────┘   └──┘   └────┘    └───┘
txt     └────────┘ └──────────┘   └──┘   └────┘    └───┘
par     └────────┘ └──────────┘   └──┘   └────┘    └───┘
pid               └─────────┘                    └─┘
st     └───────────────────────────────┘└────────┘└─────────────────────────────┘└┘
841  
842  theorem mem_foldr_permutations_aux2 {t : α} {ts : list α} {r L : list (list α)} {l' : list α} :
id                                                    └──┘          └──┘  └──┘          └──┘ 
src                                                    └──┘           └──┘  └──┘           └──┘
typ                                                   └──┘          └──┘  └──┘          └──┘ 
843    l' ∈ foldr (λy r, (permutations_aux2 t ts r y id).2) r L ↔ l' ∈ r ∨
id     └┘  └───┘       └───────────────┘  └┘   └┘       └┘   
src        └───┘         └───────────────┘          └┘               
typ    └┘  └───┘       └───────────────┘  └┘   └┘       └┘   
844    ∃ l₁ l₂, l₁ ++ l₂ ∈ L ∧ l₂ ≠ [] ∧ l' = l₁ ++ t :: l₂ ++ ts :=
id      └┘ └┘ └┘ └┘ └┘    └┘  └┘  └┘  └┘ └┘  └┘ └┘ └┘ └┘
src              └┘            └┘         └┘   └┘    └┘
typ     └┘ └┘ └┘ └┘ └┘    └┘  └┘  └┘  └┘ └┘  └┘ └┘ └┘ └┘
845  have (∃ (a : list α), a ∈ L ∧
id               └──┘      
src              └──┘         
typ              └──┘      
846      ∃ (l₁ l₂ : list α), ¬l₂ = nil ∧ a = l₁ ++ l₂ ∧ l' = l₁ ++ t :: (l₂ ++ ts)) ↔
id                 └──┘   └┘  └─┘    └┘ └┘ └┘  └┘  └┘ └┘  └┘  └┘ └┘ └┘   
src                └──┘        └─┘        └┘            └┘   └┘     └┘      
typ                └──┘   └┘  └─┘    └┘ └┘ └┘  └┘  └┘ └┘  └┘  └┘ └┘ └┘   
847      ∃ (l₁ l₂ : list α), ¬l₂ = nil ∧ l₁ ++ l₂ ∈ L ∧ l' = l₁ ++ t :: (l₂ ++ ts),
id                 └──┘   └┘  └─┘  └┘ └┘ └┘    └┘  └┘ └┘  └┘  └┘ └┘ └┘
src                └──┘        └─┘     └┘               └┘   └┘     └┘
typ                └──┘   └┘  └─┘  └┘ └┘ └┘    └┘  └┘ └┘  └┘  └┘ └┘ └┘
848  from ⟨λ ⟨a, aL, l₁, l₂, l0, e, h⟩, ⟨l₁, l₂, l0, e ▸ aL, h⟩,
id              └┘  └┘  └┘  └┘                      
src                                                    
typ             └┘  └┘  └┘  └┘                      
849        λ ⟨l₁, l₂, l0, aL, h⟩, ⟨_, aL, l₁, l₂, l0, rfl, h⟩⟩,
id           └┘  └┘  └┘  └┘                         └─┘
src                                                   └─┘
typ          └┘  └┘  └┘  └┘                         └─┘
850  by rw foldr_permutations_aux2; simp [mem_permutations_aux2', this,
id         └─────────────────────┘        └────────────────────┘  └──┘
src     └─┘└─────────────────────┘  └────┘└────────────────────┘└┘    └─
typ     └─┘└─────────────────────┘  └────┘└────────────────────┘└┘└──┘└─
doc     └─┘                         └────┘                      └┘    └─
txt     └─┘                         └────┘                      └┘    └─
par     └─┘                         └────┘                      └┘    └─
pid                                                          └┘    └─
st     └────────────────────────────────────────────────────────────────
851    or.comm, or.left_comm, or.assoc, and.comm, and.left_comm, and.assoc]
id     └─────┘  └──────────┘  └──────┘  └──────┘  └───────────┘  └───────┘
src  ─┘└─────┘└┘└──────────┘└┘└──────┘└┘└──────┘└┘└───────────┘└┘└───────┘└─
typ  ─┘└─────┘└┘└──────────┘└┘└──────┘└┘└──────┘└┘└───────────┘└┘└───────┘└─
doc  ─┘       └┘            └┘        └┘        └┘             └┘         └─
txt  ─┘       └┘            └┘        └┘        └┘             └┘         └─
par  ─┘       └┘            └┘        └┘        └┘             └┘         └─
pid  ─┘       └┘            └┘        └┘        └┘             └┘         
st   ───────────────────────────────────────────────────────────────────────
852  
src  
typ  
doc  
txt  
par  
pid  
st   
853  theorem length_foldr_permutations_aux2 (t : α) (ts : list α) (r L : list (list α)) :
id                                                       └──┘          └──┘  └──┘ 
src                                                       └──┘           └──┘  └──┘
typ                                                      └──┘          └──┘  └──┘ 
854    length (foldr (λy r, (permutations_aux2 t ts r y id).2) r L) = sum (map length L) + length r :=
id     └────┘  └───┘       └───────────────┘  └┘   └┘        └─┘  └─┘ └────┘    └────┘ 
src    └────┘  └───┘         └───────────────┘          └┘          └─┘  └─┘ └────┘     └────┘
typ    └────┘  └───┘       └───────────────┘  └┘   └┘        └─┘  └─┘ └────┘    └────┘ 
doc                                                                   └─┘
855  by simp [foldr_permutations_aux2, (∘), length_permutations_aux2]
id            └─────────────────────┘      └──────────────────────┘
src     └────┘└─────────────────────┘└┘└──┘└──────────────────────┘└─
typ     └────┘└─────────────────────┘└┘└──┘└──────────────────────┘└─
doc     └────┘                       └┘ └──┘                        └─
txt     └────┘                       └┘ └──┘                        └─
par     └────┘                       └┘ └──┘                        └─
pid                                └┘ └──┘                        
st     └──────────────────────────────────────────────────────────────
856  
src  
typ  
doc  
txt  
par  
pid  
st   
857  theorem length_foldr_permutations_aux2' (t : α) (ts : list α) (r L : list (list α))
id                                                        └──┘          └──┘  └──┘ 
src                                                        └──┘           └──┘  └──┘
typ                                                       └──┘          └──┘  └──┘ 
858    (n) (H : ∀ l ∈ L, length l = n) :
id                     └────┘   
src                      └────┘   
typ                    └────┘   
859    length (foldr (λy r, (permutations_aux2 t ts r y id).2) r L) = n * length L + length r :=
id     └────┘  └───┘       └───────────────┘  └┘   └┘          └────┘   └────┘ 
src    └────┘  └───┘         └───────────────┘          └┘             └────┘    └────┘
typ    └────┘  └───┘       └───────────────┘  └┘   └┘          └────┘   └────┘ 
860  begin
st   └─────
861    rw [length_foldr_permutations_aux2, (_ : sum (map length L) = n * length L)],
id         └────────────────────────────┘       └─┘  └─┘              └────┘ 
src    └──┘└────────────────────────────┘└┘ └──┘└─┘ └─┘       └┘ └────┘ └┘
typ    └──┘└────────────────────────────┘└┘ └──┘└─┘ └─┘       └┘└────┘└┘
doc    └──┘                              └┘ └──┘└─┘           └┘          └┘
txt    └──┘                              └┘ └──┘              └┘          └┘
par    └──┘                              └┘ └──┘              └┘          └┘
pid      └┘                              └┘ └──┘              └┘          └┘
st   ───────────────────────────────────┘└───────────────────────────────────────┘└──
862    induction L with l L ih, {simp},
id               
src    └────────┘ └──────────┘   └──┘
typ    └────────┘└──────────┘   └──┘
doc    └────────┘ └──────────┘   └──┘
txt    └────────┘ └──────────┘   └──┘
par    └────────┘ └──────────┘   └──┘
pid              └─────────┘
st   ────────────────────────┘└─────┘└┘
863    simp [ih (λ l m, H l (mem_cons_of_mem _ m)), H l (mem_cons_self _ _), mul_add]
id           └┘             └─────────────┘           └───────────┘       └─────┘
src    └────┘    └────┘   └─────────────┘└─┘ └──┘   └───────────┘└─────┘└─────┘└┘
typ    └────┘└┘  └────┘  └─────────────┘└─┘ └──┘ └───────────┘└─────┘└─────┘└┘
doc    └────┘    └────┘                  └─┘ └──┘                └─────┘       └┘
txt    └────┘    └────┘                  └─┘ └──┘                └─────┘       └┘
par    └────┘    └────┘                  └─┘ └──┘                └─────┘       └┘
pid            └────┘                  └─┘ └──┘                └─────┘       
st   ────────────────────────────────────────────────────────────────────────────────┘
864  end
st   └─┘
865  
866  theorem perm_of_mem_permutations_aux :
867    ∀ {ts is l : list α}, l ∈ permutations_aux ts is → l ~ ts ++ is :=
id                  └──┘      └──────────────┘ └┘ └┘     └┘ └┘ └┘
src                 └──┘        └──────────────┘               └┘
typ                 └──┘      └──────────────┘ └┘ └┘     └┘ └┘ └┘
doc                                                         
868  begin
st   └─────
869    refine permutations_aux.rec (by simp) _,
id            └──────────────────┘
src    └─────┘└──────────────────┘   └──┘└─┘
typ    └─────┘└──────────────────┘   └──┘└─┘
doc    └─────┘                       └──┘└─┘
txt    └─────┘                       └──┘└─┘
par    └─────┘                       └──┘└─┘
pid                                 └──────┘
st   ────────────────────────────────┘└───┘└─┘└─
870    introv IH1 IH2 m,
src    └──────────────┘
typ    └──────────────┘
doc    └──────────────┘
txt    └──────────────┘
par    └──────────────┘
pid          └────────┘
st   ─────────────────┘└─
871    rw [permutations_aux_cons, permutations, mem_foldr_permutations_aux2] at m,
id         └───────────────────┘  └──────────┘  └─────────────────────────┘
src    └──┘└───────────────────┘└┘└──────────┘└┘└─────────────────────────┘└────┘
typ    └──┘└───────────────────┘└┘└──────────┘└┘└─────────────────────────┘└────┘
doc    └──┘                     └┘└──────────┘└┘                           └────┘
txt    └──┘                     └┘            └┘                           └────┘
par    └──┘                     └┘            └┘                           └────┘
pid      └┘                     └┘            └┘                           └───┘
st   ──────────────────────────┘└────────────┘└───────────────────────────┘└───┘└─
872    rcases m with m | ⟨l₁, l₂, m, _, e⟩,
id            
src    └─────┘ └─────────────────────────┘
typ    └─────┘└─────────────────────────┘
doc    └─────┘ └─────────────────────────┘
txt    └─────┘ └─────────────────────────┘
par    └─────┘ └─────────────────────────┘
pid           └─────────────────────────┘
st   ────────────────────────────────────┘└─
873    { exact (IH1 m).trans perm_middle },
id              └─┘         └─────────┘
src      └────┘     └──────┘└─────────┘
typ      └────┘ └─┘└──────┘└─────────┘
doc      └────┘     └──────┘           
txt      └────┘     └──────┘           
par      └────┘     └──────┘           
pid                └──────┘           
st   ───┘└──────────────────────────────┘└┘
874    { subst e,
id             
src      └────┘
typ      └────┘
doc      └────┘
txt      └────┘
par      └────┘
pid           
st   ──────────┘└─
875      have p : l₁ ++ l₂ ~ is,
id                └┘ └┘ └┘  └┘
src      └───────┘  └┘  
typ      └───────┘└┘└┘└┘└┘
doc      └───────┘      
txt      └───────┘       
par      └───────┘       
pid      └────┘└─┘       
st   ─────────────────────────┘└─
876      { simp [permutations] at m,
id               └──────────┘
src        └────┘└──────────┘└────┘
typ        └────┘└──────────┘└────┘
doc        └────┘└──────────┘└────┘
txt        └────┘            └────┘
par        └────┘            └────┘
pid                        └──┘
st   ─────┘└──────────────────────┘└─
877        cases m with e m, {simp [e]},
id                                 
src        └────┘ └───────┘   └────┘ 
typ        └────┘└───────┘   └────┘
doc        └────┘ └───────┘   └────┘ 
txt        └────┘ └───────┘   └────┘ 
par        └────┘ └───────┘   └────┘ 
pid              └───────┘        
st   ─────────────────────┘└─────────┘└┘
878        exact is.append_nil ▸ IH2 m },
id               └───────────┘  └─┘ 
src        └────┘└───────────┘    
typ        └────┘└───────────┘└─┘
doc        └────┘                  
txt        └────┘                  
par        └────┘                  
pid                               
st   ─────────────────────────────────┘└┘
879      exact (perm_app_left _ (perm_middle.trans (skip _ p))).trans (skip _ perm_app_comm) }
id              └───────────┘    └───────────────┘                    └──┘   └───────────┘
src      └────┘ └───────────┘└─┘ └───────────────┘     └─┘ └────────┘ └──┘└─┘└───────────┘└┘
typ      └────┘ └───────────┘└─┘ └───────────────┘     └─┘└────────┘ └──┘└─┘└───────────┘└┘
doc      └────┘              └─┘                       └─┘ └────────┘     └─┘             └┘
txt      └────┘              └─┘                       └─┘ └────────┘     └─┘             └┘
par      └────┘              └─┘                       └─┘ └────────┘     └─┘             └┘
pid                         └─┘                       └─┘ └────────┘     └─┘             
st   ───────────────────────────────────────────────────────────────────────────────────────┘└─
880  end
st   ──┘
881  
882  theorem perm_of_mem_permutations {l₁ l₂ : list α}
id                                             └──┘ 
src                                            └──┘
typ                                            └──┘ 
883    (h : l₁ ∈ permutations l₂) : l₁ ~ l₂ :=
id          └┘  └──────────┘ └┘    └┘  └┘
src             └──────────┘          
typ         └┘  └──────────┘ └┘    └┘  └┘
doc              └──────────┘          
884  (eq_or_mem_of_mem_cons h).elim (λ e, e ▸ perm.refl _)
id    └───────────────────┘  └──┘         └───────┘
src   └───────────────────┘   └──┘           └───────┘
typ   └───────────────────┘  └──┘         └───────┘
885    (λ m, append_nil l₂ ▸ perm_of_mem_permutations_aux m)
id          └────────┘ └┘  └──────────────────────────┘ 
src          └────────┘     └──────────────────────────┘
typ         └────────┘ └┘  └──────────────────────────┘ 
886  
887  theorem length_permutations_aux :
888    ∀ ts is : list α, length (permutations_aux ts is) + is.length.fact = (length ts + length is).fact :=
id               └──┘   └────┘  └──────────────┘ └┘ └┘   └┘└─────┘└───┘   └────┘ └┘  └────┘ └┘ └──┘
src              └──┘    └────┘  └──────────────┘           └─────┘└───┘   └────┘     └────┘    └──┘
typ              └──┘   └────┘  └──────────────┘ └┘ └┘   └┘└─────┘└───┘   └────┘ └┘  └────┘ └┘ └──┘
doc                                                                 └───┘                          └──┘
889  begin
st   └─────
890    refine permutations_aux.rec (by simp) _,
id            └──────────────────┘
src    └─────┘└──────────────────┘   └──┘└─┘
typ    └─────┘└──────────────────┘   └──┘└─┘
doc    └─────┘                       └──┘└─┘
txt    └─────┘                       └──┘└─┘
par    └─────┘                       └──┘└─┘
pid                                 └──────┘
st   ────────────────────────────────┘└───┘└─┘└─
891    intros t ts is IH1 IH2,
src    └────────────────────┘
typ    └────────────────────┘
doc    └────────────────────┘
txt    └────────────────────┘
par    └────────────────────┘
pid          └──────────────┘
st   ───────────────────────┘└─
892    have IH2 : length (permutations_aux is nil) + 1 = is.length.fact,
id                └────┘  └──────────────┘    └─┘      └────────────┘
src    └─────────┘└────┘ └──────────────┘  └─┘└┘└─┘└────────────┘
typ    └─────────┘└────┘ └──────────────┘  └─┘└┘└─┘└────────────┘
doc    └─────────┘                            └┘ └─┘ └────────────┘
txt    └─────────┘                            └┘ └─┘ 
par    └─────────┘                            └┘ └─┘ 
pid    └──────┘└─┘                            └┘ └─┘ 
st   ─────────────────────────────────────────────────────────────────┘└─
893    { simpa using IH2 },
id                   └─┘
src      └──────────┘   
typ      └──────────┘└─┘
doc      └──────────┘   
txt      └──────────┘   
par      └──────────┘   
pid           └────┘   
st   ───┘└──────────────┘└┘
894    simp [-add_comm, nat.fact, nat.add_succ, mul_comm] at IH1,
id                      └──────┘  └──────────┘  └──────┘
src    └───────────────┘└──────┘└┘└──────────┘└┘└──────┘└──────┘
typ    └───────────────┘└──────┘└┘└──────────┘└┘└──────┘└──────┘
doc    └───────────────┘└──────┘└┘            └┘        └──────┘
txt    └───────────────┘        └┘            └┘        └──────┘
par    └───────────────┘        └┘            └┘        └──────┘
pid        └──────────┘        └┘            └┘        └────┘
st   ──────────────────────────────────────────────────────────┘└─
895    rw [permutations_aux_cons,
id         └───────────────────┘
src    └──┘└───────────────────┘└─
typ    └──┘└───────────────────┘└─
doc    └──┘                     └─
txt    └──┘                     └─
par    └──┘                     └─
pid      └┘                     └─
st   ──────────────────────────┘└─
896        length_foldr_permutations_aux2' _ _ _ _ _
id         └─────────────────────────────┘
src  ─────┘└─────────────────────────────┘└──────────
typ  ─────┘└─────────────────────────────┘└──────────
doc  ─────┘                               └──────────
txt  ─────┘                               └──────────
par  ─────┘                               └──────────
pid  ─────┘                               └──────────
st   ────────────────────────────────────────────────
897          (λ l m, perm_length (perm_of_mem_permutations m)),
id                   └─────────┘  └──────────────────────┘
src  ───────┘  └────┘└─────────┘ └──────────────────────┘ └───
typ  ───────┘  └────┘└─────────┘ └──────────────────────┘ └───
doc  ───────┘  └────┘                                     └───
txt  ───────┘  └────┘                                     └───
par  ───────┘  └────┘                                     └───
pid  ───────┘  └────┘                                     └───
st   ────────────────────────────────────────────────────────┘└─
898        permutations, length, length, IH2,
id         └──────────┘  └────┘  └────┘  └─┘
src  ─────┘└──────────┘└┘└────┘└┘└────┘└┘   └─
typ  ─────┘└──────────┘└┘└────┘└┘└────┘└┘└─┘└─
doc  ─────┘└──────────┘└┘      └┘      └┘   └─
txt  ─────┘            └┘      └┘      └┘   └─
par  ─────┘            └┘      └┘      └┘   └─
pid  ─────┘            └┘      └┘      └┘   └─
st   ─────────────────┘└──────┘└──────┘└───┘└─
899        nat.succ_add, nat.fact_succ, mul_comm (nat.succ _), ← IH1,
id         └──────────┘  └───────────┘  └──────┘  └──────┘       └─┘
src  ─────┘└──────────┘└┘└───────────┘└┘└──────┘ └──────┘└─────┘   └─
typ  ─────┘└──────────┘└┘└───────────┘└┘└──────┘ └──────┘└─────┘└─┘└─
doc  ─────┘            └┘             └┘                 └─────┘   └─
txt  ─────┘            └┘             └┘                 └─────┘   └─
par  ─────┘            └┘             └┘                 └─────┘   └─
pid  ─────┘            └┘             └┘                 └─────┘   └─
st   ─────────────────┘└─────────────┘└─────────────────────┘└─────┘└─
900        add_comm (_*_), add_assoc, nat.mul_succ, mul_comm]
id         └──────┘       └───────┘  └──────────┘  └──────┘
src  ─────┘└──────┘ └──┘└───────┘└┘└──────────┘└┘└──────┘└┘
typ  ─────┘└──────┘ └──┘└───────┘└┘└──────────┘└┘└──────┘└┘
doc  ─────┘          └──┘         └┘            └┘        └┘
txt  ─────┘          └──┘         └┘            └┘        └┘
par  ─────┘          └──┘         └┘            └┘        └┘
pid  ─────┘          └──┘         └┘            └┘        
st   ───────────────────┘└─────────┘└────────────┘└────────┘
901  end
st   └─┘
902  
903  theorem length_permutations (l : list α) : length (permutations l) = (length l).fact :=
id                                    └──┘     └────┘  └──────────┘     └────┘  └──┘
src                                   └──┘      └────┘  └──────────┘      └────┘   └──┘
typ                                   └──┘     └────┘  └──────────┘     └────┘  └──┘
doc                                                     └──────────┘                └──┘
904  length_permutations_aux l []
id   └─────────────────────┘  └┘
src  └─────────────────────┘   └┘
typ  └─────────────────────┘  └┘
905  
906  theorem mem_permutations_of_perm_lemma {is l : list α}
id                                                  └──┘ 
src                                                 └──┘
typ                                                 └──┘ 
907    (H : l ~ [] ++ is → (∃ ts' ~ [], l = ts' ++ is) ∨ l ∈ permutations_aux is [])
id            └┘ └┘ └┘     └─┘   └┘   └─┘ └┘ └┘     └──────────────┘ └┘ └┘
src            └┘ └┘              └┘        └┘         └──────────────┘    └┘
typ           └┘ └┘ └┘     └─┘   └┘   └─┘ └┘ └┘     └──────────────┘ └┘ └┘
doc           
908    : l ~ is → l ∈ permutations is :=
id         └┘     └──────────┘ └┘
src                 └──────────┘
typ        └┘     └──────────┘ └┘
doc                  └──────────┘
909  by simpa [permutations, perm_nil] using H
id             └──────────┘  └──────┘        
src     └─────┘└──────────┘└┘└──────┘└──────┘ 
typ     └─────┘└──────────┘└┘└──────┘└──────┘
doc     └─────┘└──────────┘└┘        └──────┘ 
txt     └─────┘            └┘        └──────┘ 
par     └─────┘            └┘        └──────┘ 
pid                      └┘        └────┘ 
st     └───────────────────────────────────────
910  
src  
typ  
doc  
txt  
par  
pid  
st   
911  theorem mem_permutations_aux_of_perm :
912    ∀ {ts is l : list α}, l ~ is ++ ts → (∃ is' ~ is, l = is' ++ ts) ∨ l ∈ permutations_aux ts is :=
id                  └──┘      └┘ └┘ └┘     └─┘   └┘   └─┘ └┘ └┘     └──────────────┘ └┘ └┘
src                 └──┘           └┘                        └┘         └──────────────┘
typ                 └──┘      └┘ └┘ └┘     └─┘   └┘   └─┘ └┘ └┘     └──────────────┘ └┘ └┘
doc                            
913  begin
st   └─────
914    refine permutations_aux.rec (by simp) _,
id            └──────────────────┘
src    └─────┘└──────────────────┘   └──┘└─┘
typ    └─────┘└──────────────────┘   └──┘└─┘
doc    └─────┘                       └──┘└─┘
txt    └─────┘                       └──┘└─┘
par    └─────┘                       └──┘└─┘
pid                                 └──────┘
st   ────────────────────────────────┘└───┘└─┘└─
915    intros t ts is IH1 IH2 l p,
src    └────────────────────────┘
typ    └────────────────────────┘
doc    └────────────────────────┘
txt    └────────────────────────┘
par    └────────────────────────┘
pid          └──────────────────┘
st   ───────────────────────────┘└─
916    rw [permutations_aux_cons, mem_foldr_permutations_aux2],
id         └───────────────────┘  └─────────────────────────┘
src    └──┘└───────────────────┘└┘└─────────────────────────┘
typ    └──┘└───────────────────┘└┘└─────────────────────────┘
doc    └──┘                     └┘                           
txt    └──┘                     └┘                           
par    └──┘                     └┘                           
pid      └┘                     └┘                           
st   ──────────────────────────┘└───────────────────────────┘└──
917    rcases IH1 (p.trans perm_middle) with ⟨is', p', e⟩ | m,
id            └─┘  └─────┘ └─────────┘
src    └─────┘    └─────┘└─────────┘└─────────────────────┘
typ    └─────┘└─┘ └─────┘└─────────┘└─────────────────────┘
doc    └─────┘                      └─────────────────────┘
txt    └─────┘                      └─────────────────────┘
par    └─────┘                      └─────────────────────┘
pid                                └─────────────────────┘
st   ───────────────────────────────────────────────────────┘└─
918    { clear p, subst e,
id                      
src      └─────┘  └────┘
typ      └─────┘  └────┘
doc      └─────┘  └────┘
txt      └─────┘  └────┘
par      └─────┘  └────┘
pid           └┘       
st   ───┘└─────┘└───────┘└─
919      rcases mem_split (perm_subset p'.symm (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩,
id              └───────┘  └─────────┘ └─────┘  └───────────┘
src      └─────┘└───────┘ └─────────┘└─────┘ └───────────┘└─────────────────────┘
typ      └─────┘└───────┘ └─────────┘└─────┘ └───────────┘└─────────────────────┘
doc      └─────┘                                          └─────────────────────┘
txt      └─────┘                                          └─────────────────────┘
par      └─────┘                                          └─────────────────────┘
pid                                                      └─────────────────────┘
st   ──────────────────────────────────────────────────────────────────────────────┘└─
920      subst is',
id             └─┘
src      └────┘
typ      └────┘└─┘
doc      └────┘
txt      └────┘
par      └────┘
pid           
st   ────────────┘└─
921      have p := perm_cons_inv (perm_middle.symm.trans p'),
id                 └───────────┘  └────────────────────┘ └┘
src      └────────┘└───────────┘ └────────────────────┘  
typ      └────────┘└───────────┘ └────────────────────┘└┘
doc      └────────┘                                      
txt      └────────┘                                      
par      └────────┘                                      
pid      └────┘└─┘                                      
st   ──────────────────────────────────────────────────────┘└─
922      cases l₂ with a l₂',
id             └┘
src      └────┘  └─────────┘
typ      └────┘└┘└─────────┘
doc      └────┘  └─────────┘
txt      └────┘  └─────────┘
par      └────┘  └─────────┘
pid             └─────────┘
st   ──────────────────────┘└─
923      { exact or.inl ⟨l₁, by simpa using p⟩ },
id               └────┘  └┘                 
src        └────┘└────┘   └┘  └──────────┘ └┘
typ        └────┘└────┘ └┘└┘  └──────────┘└┘
doc        └────┘         └┘  └──────────┘ └┘
txt        └────┘         └┘  └──────────┘ └┘
par        └────┘         └┘  └──────────┘ └┘
pid                      └┘  └───────────┘ 
st   ─────┘└──────────────────┘└────────────┘└┘└┘
924      { exact or.inr (or.inr ⟨l₁, a::l₂',
id                       └────┘  └┘    └─┘
src        └────┘       └────┘   └┘      └─
typ        └────┘       └────┘ └┘└┘  └─┘└─
doc        └────┘                └┘      └─
txt        └────┘                └┘      └─
par        └────┘                └┘      └─
pid                             └┘      └─
st   ────────────────────────────────────────
925          mem_permutations_of_perm_lemma IH2 p, by simp⟩) } },
id           └────────────────────────────┘ └─┘ 
src  ───────┘└────────────────────────────┘    └┘  └──┘└─┘
typ  ───────┘└────────────────────────────┘└─┘└┘  └──┘└─┘
doc  ───────┘                                  └┘  └──┘└─┘
txt  ───────┘                                  └┘  └──┘└─┘
par  ───────┘                                  └┘  └──┘└─┘
pid  ───────┘                                  └┘  └─────┘
st   ───────────────────────────────────────────────┘└───┘└─┘└──┘
926    { exact or.inr (or.inl m) }
id             └────┘  └────┘ 
src      └────┘└────┘ └────┘ └┘
typ      └────┘└────┘ └────┘└┘
doc      └────┘              └┘
txt      └────┘              └┘
par      └────┘              └┘
pid                         
st   ───────────────────────────┘└─
927  end
st   ──┘
928  
929  @[simp] theorem mem_permutations (s t : list α) : s ∈ permutations t ↔ s ~ t :=
id                                           └──┘       └──────────┘     
src                                          └──┘         └──────────┘      
typ                                          └──┘       └──────────┘     
doc    └──┘                                                └──────────┘       
930  ⟨perm_of_mem_permutations, mem_permutations_of_perm_lemma mem_permutations_aux_of_perm⟩
id    └──────────────────────┘  └────────────────────────────┘ └──────────────────────────┘
src   └──────────────────────┘  └────────────────────────────┘ └──────────────────────────┘
typ   └──────────────────────┘  └────────────────────────────┘ └──────────────────────────┘
931  
932  end permutations
933  
934  end list